Added alpha-beta pruning threshold to the AI and a configuration dialog
This commit is contained in:
parent
8eda941284
commit
8ea0c7a603
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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) {
|
||||||
|
82
src/dev/kske/chess/ui/AIConfigDialog.java
Normal file
82
src/dev/kske/chess/ui/AIConfigDialog.java
Normal 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; }
|
||||||
|
|
||||||
|
}
|
@ -54,14 +54,19 @@ public class MenuBar extends JMenuBar {
|
|||||||
});
|
});
|
||||||
|
|
||||||
aiMenuItem.addActionListener((evt) -> {
|
aiMenuItem.addActionListener((evt) -> {
|
||||||
players.put(Color.WHITE, new NaturalPlayer(board, Color.WHITE, overlayComponent));
|
AIConfigDialog dialog = new AIConfigDialog();
|
||||||
players.put(Color.BLACK, new AIPlayer(board, Color.BLACK, 5));
|
dialog.setVisible(true);
|
||||||
startGame();
|
if (dialog.isStartGame()) {
|
||||||
|
players.put(Color.WHITE, new NaturalPlayer(board, Color.WHITE, overlayComponent));
|
||||||
|
players.put(Color.BLACK,
|
||||||
|
new AIPlayer(board, Color.BLACK, dialog.getMaxDepth(), dialog.getAlphaBetaThreshold()));
|
||||||
|
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();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user