Version 5.0
=========== Alpha-beta pruning is the only main change.
This commit is contained in:
@ -264,12 +264,12 @@ public class Board {
|
|||||||
|
|
||||||
if(currentPlayer==Piece.WHITE) {
|
if(currentPlayer==Piece.WHITE) {
|
||||||
currentPlayer=Piece.BLACK;
|
currentPlayer=Piece.BLACK;
|
||||||
if (SuicideChess.ASCII_GAME)
|
//if (SuicideChess.ASCII_GAME)
|
||||||
System.out.println("Black: ");
|
// System.out.println("Black: ");
|
||||||
} else {
|
} else {
|
||||||
currentPlayer=Piece.WHITE;
|
currentPlayer=Piece.WHITE;
|
||||||
if (SuicideChess.ASCII_GAME)
|
//if (SuicideChess.ASCII_GAME)
|
||||||
System.out.println("White: ");
|
// System.out.println("White: ");
|
||||||
}
|
}
|
||||||
|
|
||||||
evaluateNewBoardValue(move);
|
evaluateNewBoardValue(move);
|
||||||
|
@ -14,12 +14,16 @@ import suicideChess.Square.NotAValidSquare;
|
|||||||
|
|
||||||
public class ComputerPlayer {
|
public class ComputerPlayer {
|
||||||
|
|
||||||
|
//best move found
|
||||||
|
private static Move bestMove = null;
|
||||||
|
|
||||||
|
//to tell the number of nodes searched
|
||||||
|
private static int nodesSearched;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This asks the computer to compute a move
|
* This asks the computer to compute a move
|
||||||
* @param bitboard The current status of the {@link Board}
|
* @param bitboard The current status of the {@link Board}
|
||||||
* @param color The color to play
|
|
||||||
* @return move A {@link Move}
|
* @return move A {@link Move}
|
||||||
* @throws NotAValidSquare
|
* @throws NotAValidSquare
|
||||||
* @see Board
|
* @see Board
|
||||||
@ -43,7 +47,6 @@ public class ComputerPlayer {
|
|||||||
/**
|
/**
|
||||||
* Basic MinMax
|
* Basic MinMax
|
||||||
* @param bitboard The bitboard
|
* @param bitboard The bitboard
|
||||||
* @param color The color to play
|
|
||||||
* @return The best Move found
|
* @return The best Move found
|
||||||
* @throws NotAValidSquare
|
* @throws NotAValidSquare
|
||||||
* @throws NoPieceOnSquare
|
* @throws NoPieceOnSquare
|
||||||
@ -53,6 +56,7 @@ public class ComputerPlayer {
|
|||||||
public static Move doMinMaxMove(Board bitboard) throws NotAValidSquare, NoPieceOnSquare {
|
public static Move doMinMaxMove(Board bitboard) throws NotAValidSquare, NoPieceOnSquare {
|
||||||
bestMove = null;
|
bestMove = null;
|
||||||
nodesSearched = 0;
|
nodesSearched = 0;
|
||||||
|
|
||||||
int bestScore = MinMax(bitboard, 0);
|
int bestScore = MinMax(bitboard, 0);
|
||||||
if (SuicideChess.postThinkingOutput()) {
|
if (SuicideChess.postThinkingOutput()) {
|
||||||
System.out.println(SuicideChess.PLY_DEPTH+" "+bestScore*100+" 0 "+nodesSearched+" "+bestMove);
|
System.out.println(SuicideChess.PLY_DEPTH+" "+bestScore*100+" 0 "+nodesSearched+" "+bestMove);
|
||||||
@ -115,12 +119,120 @@ public class ComputerPlayer {
|
|||||||
|
|
||||||
//select one of the best moves randomly
|
//select one of the best moves randomly
|
||||||
Random generator = new Random();
|
Random generator = new Random();
|
||||||
|
if (currentDepth == 0) { System.out.println(bestMoveIndex.size()); }
|
||||||
bestMove = allLegalMoves.get(bestMoveIndex.get(generator.nextInt(bestMoveIndex.size())));
|
bestMove = allLegalMoves.get(bestMoveIndex.get(generator.nextInt(bestMoveIndex.size())));
|
||||||
|
|
||||||
return bestScoreSoFar;
|
return bestScoreSoFar;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Alpha-Beta
|
||||||
|
* @param bitboard The bitboard
|
||||||
|
* @return The best Move found
|
||||||
|
* @throws NotAValidSquare
|
||||||
|
* @throws NoPieceOnSquare
|
||||||
|
* @see Board
|
||||||
|
* @see Move
|
||||||
|
*/
|
||||||
|
public static Move doAlphaBetaMove(Board bitboard) throws NotAValidSquare, NoPieceOnSquare {
|
||||||
|
bestMove = null;
|
||||||
|
nodesSearched = 0;
|
||||||
|
|
||||||
|
int bestScore = AlphaBeta(bitboard, 0, Board.BLACK_WINS-1, Board.WHITE_WINS+1);
|
||||||
|
if (SuicideChess.postThinkingOutput()) {
|
||||||
|
System.out.println(SuicideChess.PLY_DEPTH+" "+bestScore*100+" 0 "+nodesSearched+" "+bestMove);
|
||||||
|
}
|
||||||
|
|
||||||
|
return bestMove;
|
||||||
|
}
|
||||||
|
|
||||||
private static Move bestMove = null;
|
|
||||||
private static int nodesSearched;
|
private static int AlphaBeta(Board bitboard, int currentDepth, int alpha, int beta) throws NotAValidSquare, NoPieceOnSquare {
|
||||||
|
if (currentDepth >= SuicideChess.PLY_DEPTH) {
|
||||||
|
return bitboard.getBoardValue();
|
||||||
|
}
|
||||||
|
|
||||||
|
nodesSearched++;
|
||||||
|
//System.out.println(currentDepth + " : " + alpha + " " + beta);
|
||||||
|
|
||||||
|
Rules.legalMovesForPlayer(bitboard);
|
||||||
|
ArrayList<Move> allLegalMoves = Rules.getLegalMovesCapture();
|
||||||
|
if (allLegalMoves.size()==0) {
|
||||||
|
allLegalMoves = Rules.getLegalMovesNonCapture();
|
||||||
|
}
|
||||||
|
if (allLegalMoves.size()==0) {
|
||||||
|
if (bitboard.getCurrentPlayer()==Piece.BLACK) {
|
||||||
|
return Board.BLACK_WINS;
|
||||||
|
} else {
|
||||||
|
return Board.WHITE_WINS;
|
||||||
|
}
|
||||||
|
|
||||||
|
} else {
|
||||||
|
ArrayList<Integer> bestMoveIndex=new ArrayList<Integer>();
|
||||||
|
int bestScoreSoFar;
|
||||||
|
int currentScore;
|
||||||
|
if (bitboard.getCurrentPlayer()==Piece.BLACK) {
|
||||||
|
bestScoreSoFar=Board.WHITE_WINS+1; //any move even a WHITE_WINS will be better than that
|
||||||
|
for (int i=0; i<allLegalMoves.size(); i++) {
|
||||||
|
Board boardCopy = new Board(bitboard);
|
||||||
|
boardCopy.doMove(allLegalMoves.get(i));
|
||||||
|
currentScore=AlphaBeta(boardCopy,currentDepth+1,alpha,beta);
|
||||||
|
beta = Math.min(beta,currentScore);
|
||||||
|
if ((currentScore <= bestScoreSoFar)) { //black tries to minimise his score
|
||||||
|
if (currentScore<bestScoreSoFar) {
|
||||||
|
bestScoreSoFar = currentScore;
|
||||||
|
bestMoveIndex.clear();
|
||||||
|
}
|
||||||
|
bestMoveIndex.add(i);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//select one of the best moves randomly
|
||||||
|
Random generator = new Random();
|
||||||
|
//if (currentDepth == 0) { System.out.println(bestMoveIndex.size()); }
|
||||||
|
bestMove = allLegalMoves.get(bestMoveIndex.get(generator.nextInt(bestMoveIndex.size())));
|
||||||
|
|
||||||
|
//System.out.println(currentDepth + " : " + alpha + " " + beta);
|
||||||
|
|
||||||
|
if(beta<=alpha) {
|
||||||
|
return alpha; //pruning
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return beta;
|
||||||
|
} else { //white piece
|
||||||
|
bestScoreSoFar=Board.BLACK_WINS-1; //any move even a BLACK_WINS will be better than that
|
||||||
|
//alpha, highest score seen so far by Max in minmax
|
||||||
|
alpha = Board.BLACK_WINS-1;
|
||||||
|
|
||||||
|
for (int i=0; i<allLegalMoves.size(); i++) {
|
||||||
|
Board boardCopy = new Board(bitboard);
|
||||||
|
boardCopy.doMove(allLegalMoves.get(i));
|
||||||
|
currentScore=AlphaBeta(boardCopy,currentDepth+1,alpha,beta);
|
||||||
|
alpha = Math.max(alpha,currentScore);
|
||||||
|
if ((currentScore >= bestScoreSoFar)) { //white tries to maximise his score
|
||||||
|
if (currentScore>bestScoreSoFar) {
|
||||||
|
bestScoreSoFar = currentScore;
|
||||||
|
bestMoveIndex.clear();
|
||||||
|
}
|
||||||
|
bestMoveIndex.add(i);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//select one of the best moves randomly
|
||||||
|
Random generator = new Random();
|
||||||
|
//if (currentDepth == 0) { System.out.println(bestMoveIndex.size()); }
|
||||||
|
bestMove = allLegalMoves.get(bestMoveIndex.get(generator.nextInt(bestMoveIndex.size())));
|
||||||
|
|
||||||
|
//System.out.println(currentDepth + " : " + alpha + " " + beta);
|
||||||
|
|
||||||
|
if(alpha>=beta) {
|
||||||
|
return beta; //pruning
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return alpha;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
@ -33,7 +33,7 @@ public class SuicideChess {
|
|||||||
/**
|
/**
|
||||||
* The name to be displayed
|
* The name to be displayed
|
||||||
*/
|
*/
|
||||||
public static final String NAME = "djib's SuShi (Suicide Chess) v0.4.3";
|
public static final String NAME = "djib's SuShi (Suicide Chess) v0.5";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Displays informations in the console.
|
* Displays informations in the console.
|
||||||
@ -43,7 +43,7 @@ public class SuicideChess {
|
|||||||
/**
|
/**
|
||||||
* Number of Plies the computes searches to
|
* Number of Plies the computes searches to
|
||||||
*/
|
*/
|
||||||
public static final int PLY_DEPTH = 4;
|
public static final int PLY_DEPTH = 6;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Test and display if the board is in a winning state.
|
* Test and display if the board is in a winning state.
|
||||||
@ -276,7 +276,7 @@ public class SuicideChess {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (computerPlaying) {
|
if (computerPlaying) {
|
||||||
Move computerMove = ComputerPlayer.doMinMaxMove(bitboard);
|
Move computerMove = ComputerPlayer.doAlphaBetaMove(bitboard);
|
||||||
bitboard.doMove(computerMove);
|
bitboard.doMove(computerMove);
|
||||||
addPlayedPosition(bitboard);
|
addPlayedPosition(bitboard);
|
||||||
XBoardProtocol.doMove(computerMove);
|
XBoardProtocol.doMove(computerMove);
|
||||||
|
Reference in New Issue
Block a user