diff --git a/src/dev/kske/chess/board/Board.java b/src/dev/kske/chess/board/Board.java
index 5f7347e..9c29145 100644
--- a/src/dev/kske/chess/board/Board.java
+++ b/src/dev/kske/chess/board/Board.java
@@ -131,6 +131,36 @@ public class Board {
: getMoves(color).isEmpty() ? GameEventType.STALEMATE : GameEventType.NONE;
}
+ /**
+ * Evaluated the board.
+ *
+ * @param color The color to evaluate for
+ * @return An positive number representing how good the position is
+ */
+ public int evaluate(Color color) {
+ int score = 0;
+ for (int i = 0; i < 8; i++)
+ for (int j = 0; j < 8; j++)
+ if (boardArr[i][j] != null && boardArr[i][j].getColor() == color) switch (boardArr[i][j].getType()) {
+ case QUEEN:
+ score += 8;
+ break;
+ case ROOK:
+ score += 5;
+ break;
+ case KNIGHT:
+ score += 3;
+ break;
+ case BISHOP:
+ score += 3;
+ break;
+ case PAWN:
+ score += 1;
+ break;
+ }
+ return score;
+ }
+
public void registerGameEventListener(GameEventListener listener) {
gameEventListeners.add(listener);
}
diff --git a/src/dev/kske/chess/game/AIPlayer.java b/src/dev/kske/chess/game/AIPlayer.java
new file mode 100644
index 0000000..4dad40d
--- /dev/null
+++ b/src/dev/kske/chess/game/AIPlayer.java
@@ -0,0 +1,47 @@
+package dev.kske.chess.game;
+
+import dev.kske.chess.board.Board;
+import dev.kske.chess.board.Move;
+import dev.kske.chess.board.Piece;
+import dev.kske.chess.board.Piece.Color;
+
+/**
+ * Project: Chess
+ * File: AIPlayer.java
+ * Created: 06.07.2019
+ * Author: Kai S. K. Engelbart
+ */
+public class AIPlayer extends Player {
+
+ private Move bestMove;
+
+ public AIPlayer(Board board, Color color) {
+ super(board, color);
+ }
+
+ @Override
+ public void requestMove() {
+ findBestMove(board, color, 0);
+ game.onMove(this, bestMove);
+ }
+
+ private int findBestMove(Board board, Color color, int depth) {
+ int bestValue = Integer.MIN_VALUE;
+ for (Move move : board.getMoves(color)) {
+ Piece capturePiece = board.move(move);
+ int teamValue = board.evaluate(color);
+ int enemyValue = board.evaluate(color.opposite());
+ int valueChange = teamValue - enemyValue;
+
+ if (depth < 4) valueChange -= findBestMove(board, color.opposite(), depth + 1);
+
+ if (valueChange > bestValue) {
+ bestValue = valueChange;
+ if (depth == 0) bestMove = move;
+ }
+
+ board.revert(move, capturePiece);
+ }
+ return bestValue;
+ }
+}
diff --git a/src/dev/kske/chess/game/Game.java b/src/dev/kske/chess/game/Game.java
index 80fad76..487a421 100644
--- a/src/dev/kske/chess/game/Game.java
+++ b/src/dev/kske/chess/game/Game.java
@@ -5,6 +5,7 @@ import java.util.Map;
import dev.kske.chess.board.Board;
import dev.kske.chess.board.Move;
import dev.kske.chess.board.Piece.Color;
+import dev.kske.chess.ui.BoardPanel;
/**
* Project: Chess
@@ -16,10 +17,12 @@ public class Game {
private Map players;
private Board board;
+ private BoardPanel boardPanel;
- public Game(Map players, Board board) {
+ public Game(Map players, Board board, BoardPanel boardPanel) {
this.players = players;
this.board = board;
+ this.boardPanel = boardPanel;
// Initialize the game variable in each player
players.values().forEach(player -> player.setGame(this));
@@ -32,6 +35,7 @@ public class Game {
public void onMove(Player player, Move move) {
if (board.getPos(move).getColor() == player.color && board.attemptMove(move)) {
System.out.printf("%s: %s%n", player.color, move);
+ boardPanel.repaint();
players.get(player.color.opposite()).requestMove();
} else {
System.out.printf("%s: Illegal move!%n", player.getColor());
diff --git a/src/dev/kske/chess/ui/GameModeDialog.java b/src/dev/kske/chess/ui/GameModeDialog.java
index 5461767..fbc8835 100644
--- a/src/dev/kske/chess/ui/GameModeDialog.java
+++ b/src/dev/kske/chess/ui/GameModeDialog.java
@@ -8,6 +8,7 @@ import javax.swing.JButton;
import javax.swing.JDialog;
import dev.kske.chess.board.Piece.Color;
+import dev.kske.chess.game.AIPlayer;
import dev.kske.chess.game.Game;
import dev.kske.chess.game.NaturalPlayer;
import dev.kske.chess.game.Player;
@@ -29,7 +30,7 @@ public class GameModeDialog extends JDialog {
super();
setModal(true);
setTitle("Game Mode Selection");
- setBounds(100, 100, 231, 99);
+ setBounds(100, 100, 231, 133);
setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE);
getContentPane().setLayout(new FlowLayout(FlowLayout.CENTER, 5, 5));
@@ -38,12 +39,29 @@ public class GameModeDialog extends JDialog {
Map players = new HashMap<>();
players.put(Color.WHITE, new NaturalPlayer(boardPanel.getBoard(), Color.WHITE, boardPanel));
players.put(Color.BLACK, new NaturalPlayer(boardPanel.getBoard(), Color.BLACK, boardPanel));
- new Game(players, boardPanel.getBoard()).start();
+ new Game(players, boardPanel.getBoard(), boardPanel).start();
dispose();
});
getContentPane().add(btnNatural);
JButton btnAI = new JButton("Game against AI");
+ btnAI.addActionListener((evt) -> {
+ Map players = new HashMap<>();
+ players.put(Color.WHITE, new NaturalPlayer(boardPanel.getBoard(), Color.WHITE, boardPanel));
+ players.put(Color.BLACK, new AIPlayer(boardPanel.getBoard(), Color.BLACK));
+ new Game(players, boardPanel.getBoard(), boardPanel).start();
+ dispose();
+ });
getContentPane().add(btnAI);
+
+ JButton btnAI2 = new JButton("AI against AI");
+ btnAI2.addActionListener((evt) -> {
+ Map players = new HashMap<>();
+ players.put(Color.WHITE, new AIPlayer(boardPanel.getBoard(), Color.WHITE));
+ players.put(Color.BLACK, new AIPlayer(boardPanel.getBoard(), Color.BLACK));
+ new Game(players, boardPanel.getBoard(), boardPanel).start();
+ dispose();
+ });
+ getContentPane().add(btnAI2);
}
}