Added alpha-beta pruning threshold to the AI and a configuration dialog

This commit is contained in:
Kai S. K. Engelbart 2019-07-16 14:42:10 +02:00
parent 8eda941284
commit 8ea0c7a603
4 changed files with 102 additions and 10 deletions

View File

@ -25,14 +25,16 @@ public class AIPlayer extends Player {
private int availableProcessors; private int availableProcessors;
private int maxDepth; private int maxDepth;
private int alphaBetaThreshold;
private volatile boolean exitRequested; private volatile boolean exitRequested;
private volatile ExecutorService executor; private volatile ExecutorService executor;
public AIPlayer(Board board, Color color, int maxDepth) { public AIPlayer(Board board, Color color, int maxDepth, int alphaBetaThreshold) {
super(board, color); super(board, color);
availableProcessors = Runtime.getRuntime().availableProcessors(); availableProcessors = Runtime.getRuntime().availableProcessors();
this.maxDepth = maxDepth; this.maxDepth = maxDepth;
this.alphaBetaThreshold = alphaBetaThreshold;
exitRequested = false; exitRequested = false;
} }
@ -62,7 +64,8 @@ public class AIPlayer extends Player {
if (rem-- > 0) ++endIndex; if (rem-- > 0) ++endIndex;
endIndex += step; endIndex += step;
processors.add( processors.add(
new MoveProcessor((Board) board.clone(), moves.subList(beginIndex, endIndex), color, maxDepth)); new MoveProcessor((Board) board.clone(), moves.subList(beginIndex, endIndex), color, maxDepth,
alphaBetaThreshold));
beginIndex = endIndex; beginIndex = endIndex;
} }

View File

@ -16,17 +16,19 @@ import dev.kske.chess.board.Piece.Color;
public class MoveProcessor implements Callable<ProcessingResult> { public class MoveProcessor implements Callable<ProcessingResult> {
private final Board board; private final Board board;
private final List<Move> rootMoves;; private final List<Move> rootMoves;
private final Color color; private final Color color;
private final int maxDepth; private final int maxDepth;
private final int alphaBetaThreshold;
private Move bestMove; private Move bestMove;
public MoveProcessor(Board board, List<Move> rootMoves, Color color, int maxDepth) { public MoveProcessor(Board board, List<Move> rootMoves, Color color, int maxDepth, int alphaBetaThreshold) {
this.board = board; this.board = board;
this.rootMoves = rootMoves; this.rootMoves = rootMoves;
this.color = color; this.color = color;
this.maxDepth = maxDepth; this.maxDepth = maxDepth;
this.alphaBetaThreshold = alphaBetaThreshold;
} }
@Override @Override
@ -43,7 +45,7 @@ public class MoveProcessor implements Callable<ProcessingResult> {
int enemyValue = board.evaluate(color.opposite()); int enemyValue = board.evaluate(color.opposite());
int valueChange = teamValue - enemyValue; int valueChange = teamValue - enemyValue;
if (depth < maxDepth && valueChange >= 0) if (depth < maxDepth && valueChange >= alphaBetaThreshold)
valueChange -= miniMax(board, board.getMoves(color.opposite()), color.opposite(), depth + 1); valueChange -= miniMax(board, board.getMoves(color.opposite()), color.opposite(), depth + 1);
if (valueChange > bestValue) { if (valueChange > bestValue) {

View File

@ -0,0 +1,82 @@
package dev.kske.chess.ui;
import java.awt.Dimension;
import javax.swing.JButton;
import javax.swing.JDialog;
import javax.swing.JLabel;
import javax.swing.JSpinner;
import javax.swing.SpinnerNumberModel;
/**
* Project: <strong>Chess</strong><br>
* File: <strong>AIConfigDialog.java</strong><br>
* Created: <strong>16.07.2019</strong><br>
* Author: <strong>Kai S. K. Engelbart</strong>
*/
public class AIConfigDialog extends JDialog {
private static final long serialVersionUID = -8047984368152479992L;
private int maxDepth;
private int alphaBetaThreshold;
private boolean startGame = false;
public AIConfigDialog() {
setSize(new Dimension(293, 212));
setModal(true);
setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE);
setTitle("AI Configuration");
getContentPane().setLayout(null);
JSpinner spAlphaBetaThreshold = new JSpinner();
spAlphaBetaThreshold.setBounds(170, 0, 95, 28);
getContentPane().add(spAlphaBetaThreshold);
spAlphaBetaThreshold.setModel(new SpinnerNumberModel(-10, -100, 100, 5));
JSpinner spMaxDepth = new JSpinner();
spMaxDepth.setBounds(170, 68, 95, 28);
getContentPane().add(spMaxDepth);
spMaxDepth.setModel(new SpinnerNumberModel(4, 1, 10, 1));
JLabel lblAlphabetaThreshold = new JLabel("Alpha-Beta Threshold:");
lblAlphabetaThreshold.setBounds(16, 68, 119, 28);
getContentPane().add(lblAlphabetaThreshold);
JButton btnOk = new JButton("OK");
btnOk.setBounds(16, 137, 84, 28);
getContentPane().add(btnOk);
btnOk.addActionListener((evt) -> {
maxDepth = ((Integer) spMaxDepth.getValue()).intValue();
alphaBetaThreshold = ((Integer) spAlphaBetaThreshold.getValue()).intValue();
startGame = true;
dispose();
});
btnOk.setToolTipText("Start the game");
JButton btnCancel = new JButton("Cancel");
btnCancel.setBounds(170, 137, 95, 28);
getContentPane().add(btnCancel);
btnCancel.addActionListener((evt) -> dispose());
btnCancel.setToolTipText("Cancel the game start");
JLabel lblMaximalRecursionDepth = new JLabel("Maximal Recursion Depth:");
lblMaximalRecursionDepth.setBounds(16, 6, 141, 16);
getContentPane().add(lblMaximalRecursionDepth);
setLocationRelativeTo(null);
}
public int getMaxDepth() { return maxDepth; }
public void setMaxDepth(int maxDepth) { this.maxDepth = maxDepth; }
public int getAlphaBetaThreshold() { return alphaBetaThreshold; }
public void setAlphaBetaThreshold(int alphaBetaThreshold) { this.alphaBetaThreshold = alphaBetaThreshold; }
public boolean isStartGame() { return startGame; }
public void setStartGame(boolean startGame) { this.startGame = startGame; }
}

View File

@ -54,14 +54,19 @@ public class MenuBar extends JMenuBar {
}); });
aiMenuItem.addActionListener((evt) -> { aiMenuItem.addActionListener((evt) -> {
AIConfigDialog dialog = new AIConfigDialog();
dialog.setVisible(true);
if (dialog.isStartGame()) {
players.put(Color.WHITE, new NaturalPlayer(board, Color.WHITE, overlayComponent)); players.put(Color.WHITE, new NaturalPlayer(board, Color.WHITE, overlayComponent));
players.put(Color.BLACK, new AIPlayer(board, Color.BLACK, 5)); players.put(Color.BLACK,
new AIPlayer(board, Color.BLACK, dialog.getMaxDepth(), dialog.getAlphaBetaThreshold()));
startGame(); startGame();
}
}); });
aiVsAiMenuItem.addActionListener((evt) -> { aiVsAiMenuItem.addActionListener((evt) -> {
players.put(Color.WHITE, new AIPlayer(board, Color.WHITE, 5)); players.put(Color.WHITE, new AIPlayer(board, Color.WHITE, 4, -10));
players.put(Color.BLACK, new AIPlayer(board, Color.BLACK, 4)); players.put(Color.BLACK, new AIPlayer(board, Color.BLACK, 3, 0));
startGame(); startGame();
}); });