The computer plays with minmax and detects the end of games
No known bugs
This commit is contained in:
2006-01-27 23:34:09 +00:00
parent 5266b582bb
commit 213b1e3bf0
8 changed files with 225 additions and 193 deletions

11
TODO
View File

@ -2,3 +2,14 @@ Have a look at all the checks that are done.
Add constants for useless ones. Add constants for useless ones.
Look at what should be static Look at what should be static
Detect end of game.
This will be done with heuristics because number of pieces on the games will be a parameter of the heuristic function.
Be able to let the computer play against himself.
I haven't implemented the draw at all !!!
Allow undo.
Improve speed by adding a function : is there a legal move ?

View File

@ -31,12 +31,8 @@ public class Board {
private static final int NB_OF_BITBOARDS = 14; private static final int NB_OF_BITBOARDS = 14;
@SuppressWarnings("serial")
public class NoPieceOnSquare extends Exception { public class NoPieceOnSquare extends Exception {
/*
* Added by Eclipse
*/
private static final long serialVersionUID = -2750943856086117656L;
NoPieceOnSquare(String s) { super(s); }; NoPieceOnSquare(String s) { super(s); };
} }
@ -88,6 +84,9 @@ public class Board {
*/ */
public Board() throws NotAValidSquare { public Board() throws NotAValidSquare {
//the following line makes sure that enPassantSquare is defined at some point.
enPassantSquare = new Square("a1");
bitBoards = new long[NB_OF_BITBOARDS]; bitBoards = new long[NB_OF_BITBOARDS];
addPiece(new Square("a1"),new Piece(Piece.WHITE_ROOK)); addPiece(new Square("a1"),new Piece(Piece.WHITE_ROOK));
addPiece(new Square("b1"),new Piece(Piece.WHITE_KNIGHT)); addPiece(new Square("b1"),new Piece(Piece.WHITE_KNIGHT));
@ -141,7 +140,7 @@ public class Board {
this.bitBoards[i] = bitboard.bitBoards[i]; this.bitBoards[i] = bitboard.bitBoards[i];
} }
this.enPassant = bitboard.enPassant; this.enPassant = bitboard.enPassant;
this.enPassantSquare = bitboard.enPassantSquare; this.enPassantSquare = new Square(bitboard.enPassantSquare);
} }
/*================* /*================*
@ -163,8 +162,6 @@ public class Board {
} else { } else {
removePiece(move.toSquare(), move.getCapturedPiece()); removePiece(move.toSquare(), move.getCapturedPiece());
} }
//capture moves change the value of the board
evaluateNewBoardValue(move);
} }
removePiece(move.fromSquare(), move.getMovingPiece()); removePiece(move.fromSquare(), move.getMovingPiece());
if (move.isPromotionMove()) { if (move.isPromotionMove()) {
@ -179,7 +176,7 @@ public class Board {
enPassantSquare=move.getEnPassantSquare(); enPassantSquare=move.getEnPassantSquare();
} }
evaluateNewBoardValue(move);
} }
/** /**
@ -421,6 +418,15 @@ public class Board {
boardValue = numberOfBlackPieces - numberOfWhitePieces; boardValue = numberOfBlackPieces - numberOfWhitePieces;
} }
} }
if ((Rules.getLegalMovesCapture().size()==0)&&(Rules.getLegalMovesNonCapture().size()==0)) {
// The following line is NOT an error !!!
// After move from WHITE, if there is no moves for BLACK, BLACK won.
if (move.getMovingPiece().getColor()==Piece.WHITE) {
boardValue = BLACK_WINS;
} else {
boardValue = WHITE_WINS;
}
}
} }
} }

View File

@ -16,13 +16,6 @@ public class ComputerPlayer {
/**
* This constructor creates a computer.
*/
public ComputerPlayer() {
//this.color = color;
}
/** /**
* 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}
@ -32,7 +25,7 @@ public class ComputerPlayer {
* @see Board * @see Board
* @see Move * @see Move
*/ */
public Move doRandomMove(Board bitboard, int color) throws NotAValidSquare { public static Move doRandomMove(Board bitboard, int color) throws NotAValidSquare {
Random generator = new Random(); Random generator = new Random();
Rules.legalMovesForPlayer(bitboard,color); Rules.legalMovesForPlayer(bitboard,color);
ArrayList<Move> allLegalMoves = Rules.getLegalMovesCapture(); ArrayList<Move> allLegalMoves = Rules.getLegalMovesCapture();
@ -57,14 +50,14 @@ public class ComputerPlayer {
* @see Board * @see Board
* @see Move * @see Move
*/ */
public Move doMinMaxMove(Board bitboard, int color) throws NotAValidSquare, NoPieceOnSquare { public static Move doMinMaxMove(Board bitboard, int color) throws NotAValidSquare, NoPieceOnSquare {
bestMove = null; bestMove = null;
MinMax(bitboard, color, 0); MinMax(bitboard, color, 0);
return bestMove; return bestMove;
} }
private int MinMax(Board bitboard, int color, int currentDepth) throws NotAValidSquare, NoPieceOnSquare { private static int MinMax(Board bitboard, int color, int currentDepth) throws NotAValidSquare, NoPieceOnSquare {
if (currentDepth >= SuicideChess.PLY_DEPTH) { if (currentDepth >= SuicideChess.PLY_DEPTH) {
return bitboard.getBoardValue(); return bitboard.getBoardValue();
} }

View File

@ -32,12 +32,8 @@ public class Move {
private boolean isEnPassant=false; private boolean isEnPassant=false;
private Square enPassantSquare; private Square enPassantSquare;
@SuppressWarnings("serial")
public class NotAValidMoveException extends Exception { public class NotAValidMoveException extends Exception {
/*
* Generated by Eclipse
*/
private static final long serialVersionUID = 2194133427162274651L;
NotAValidMoveException(String s) { super(s); }; NotAValidMoveException(String s) { super(s); };
} }

View File

@ -69,7 +69,6 @@ public class Rules {
public static void legalMovesFromSquare(Square fromSquare, Board board) throws NotAValidSquare { public static void legalMovesFromSquare(Square fromSquare, Board board) throws NotAValidSquare {
Move validMove; Move validMove;
Square toSquare; Square toSquare;
Piece movingPiece = board.getPiece(fromSquare); Piece movingPiece = board.getPiece(fromSquare);
switch (movingPiece.getPieceType()) { switch (movingPiece.getPieceType()) {
case Piece.NONE: case Piece.NONE:
@ -262,17 +261,15 @@ public class Rules {
break; break;
default: default:
int pieceType = movingPiece.getPieceType();
int bitboardSquare = Board.squareToBitBoardSquare(fromSquare);
//look for all valid moves //look for all valid moves
for (int ray=0; for (int ray=0; ray<movesAllowed[pieceType][bitboardSquare].length; ray++) {
ray<movesAllowed[movingPiece.getPieceType()][Board.squareToBitBoardSquare(fromSquare)].length; try {
ray++) { for (int moveNumber=0; moveNumber<movesAllowed[pieceType][bitboardSquare][ray].length; moveNumber++) {
for (int moveNumber=0;
moveNumber<movesAllowed[movingPiece.getPieceType()][Board.squareToBitBoardSquare(fromSquare)][ray].length;
moveNumber++) {
toSquare = toSquare =
new Square(movesAllowed[movingPiece.getPieceType()] new Square(movesAllowed[pieceType][bitboardSquare][ray][moveNumber]);
[Board.squareToBitBoardSquare(fromSquare)][ray][moveNumber]);
//first check if there is a piece of the same color on that square //first check if there is a piece of the same color on that square
if (board.getPiece(toSquare).getColor()==movingPiece.getColor()) { if (board.getPiece(toSquare).getColor()==movingPiece.getColor()) {
@ -288,8 +285,11 @@ public class Rules {
} else { } else {
legalMovesNonCapture.add(validMove); legalMovesNonCapture.add(validMove);
} }
}//end for moveNumber }//end for moveNumber
} catch (Exception e) {
throw new RuntimeException("pieceType:"+pieceType+" bitboardSquare:"+bitboardSquare+
" ray:"+ray+" movesAllowed[pieceType][bitboardSquare][ray]:"+movesAllowed[pieceType][bitboardSquare][ray]);
}
}//end for ray }//end for ray
} //end case } //end case
@ -4843,7 +4843,6 @@ public class Rules {
movesAllowed[Piece.QUEEN][ 45 ][ 2 ][ 4 ] = 5; movesAllowed[Piece.QUEEN][ 45 ][ 2 ][ 4 ] = 5;
movesAllowed[Piece.QUEEN][ 45 ][ 3 ][ 0 ] = 53; movesAllowed[Piece.QUEEN][ 45 ][ 3 ][ 0 ] = 53;
movesAllowed[Piece.QUEEN][ 45 ][ 3 ][ 1 ] = 61; movesAllowed[Piece.QUEEN][ 45 ][ 3 ][ 1 ] = 61;
movesAllowed[Piece.QUEEN][ 45 ] = new int[ 8 ][];
movesAllowed[Piece.QUEEN][ 45 ][ 4 ] = new int[ 5 ]; movesAllowed[Piece.QUEEN][ 45 ][ 4 ] = new int[ 5 ];
movesAllowed[Piece.QUEEN][ 45 ][ 5 ] = new int[ 2 ]; movesAllowed[Piece.QUEEN][ 45 ][ 5 ] = new int[ 2 ];
movesAllowed[Piece.QUEEN][ 45 ][ 6 ] = new int[ 2 ]; movesAllowed[Piece.QUEEN][ 45 ][ 6 ] = new int[ 2 ];

View File

@ -13,12 +13,8 @@ public class Square {
private int fileNb; private int fileNb;
private int rank; private int rank;
@SuppressWarnings("serial")
public class NotAValidSquare extends Exception { public class NotAValidSquare extends Exception {
/*
* Generated by Eclipse
*/
private static final long serialVersionUID = 7586171991212094565L;
NotAValidSquare(String s) { super(s); }; NotAValidSquare(String s) { super(s); };
} }
@ -47,6 +43,15 @@ public class Square {
} }
} }
/**
* Constructs a Square by copying another square
*/
public Square(Square square) {
this.file = square.file;
this.fileNb = square.fileNb;
this.rank = square.rank;
}
/** /**
* Construcs a Square given a bitboard square (number from 0 to 63) * Construcs a Square given a bitboard square (number from 0 to 63)
* @param bitboardSquare An integer representing the bitboard square * @param bitboardSquare An integer representing the bitboard square

View File

@ -65,6 +65,23 @@ public class SuicideChess {
} }
} }
/**
* Test and display if the board is in a winning state.
* @param bitboard A Board
* @return True or False
*/
private static boolean testWinningPosition (Board bitboard) {
if (bitboard.getBoardValue()==Board.BLACK_WINS) {
System.out.println("0-1 {Black mates}");
return true;
} else if (bitboard.getBoardValue()==Board.WHITE_WINS) {
System.out.println("1-0 {White mates}");
return true;
}
return false;
}
/** /**
* If feature usermove has not been accepted by XBoard then consider all unknown commands * If feature usermove has not been accepted by XBoard then consider all unknown commands
* as moves * as moves
@ -95,7 +112,6 @@ public class SuicideChess {
System.out.println("White: "); System.out.println("White: ");
} }
ComputerPlayer computer = new ComputerPlayer();
boolean computerPlaying = true; //the computer does not play in foce mode. boolean computerPlaying = true; //the computer does not play in foce mode.
boolean playing = true; boolean playing = true;
@ -132,7 +148,7 @@ public class SuicideChess {
System.out.println("variant suicide"); System.out.println("variant suicide");
break; break;
case XBoardProtocol.HINT: case XBoardProtocol.HINT:
System.out.println("Hint: "+computer.doRandomMove(bitboard,currentPlayerColor)); System.out.println("Hint: "+ComputerPlayer.doRandomMove(bitboard,currentPlayerColor));
break; break;
case XBoardProtocol.FORCE: case XBoardProtocol.FORCE:
computerPlaying = false; computerPlaying = false;
@ -193,6 +209,10 @@ public class SuicideChess {
System.out.println("Illegal move: "+theMove.toString()); System.out.println("Illegal move: "+theMove.toString());
} }
if (testWinningPosition(bitboard)) {
computerPlaying=false;
}
if (!playedALegalMove) { if (!playedALegalMove) {
break; break;
} }
@ -205,7 +225,7 @@ public class SuicideChess {
if (xBoardCommand==XBoardProtocol.GO) if (xBoardCommand==XBoardProtocol.GO)
computerPlaying = true; computerPlaying = true;
if (computerPlaying) { if (computerPlaying) {
Move computerMove = computer.doMinMaxMove(bitboard,currentPlayerColor); Move computerMove = ComputerPlayer.doMinMaxMove(bitboard,currentPlayerColor);
bitboard.doMove(computerMove); bitboard.doMove(computerMove);
XBoardProtocol.doMove(computerMove); XBoardProtocol.doMove(computerMove);
if (ASCII_GAME) { if (ASCII_GAME) {
@ -215,8 +235,11 @@ public class SuicideChess {
} }
changeCurrentPlayerColor(); changeCurrentPlayerColor();
} }
break; if (testWinningPosition(bitboard)) {
computerPlaying=false;
}
break;
} }
// if (whatMove.startsWith("hint")) { // if (whatMove.startsWith("hint")) {
@ -255,9 +278,8 @@ public class SuicideChess {
} catch (NotAValidSquare err) { } catch (NotAValidSquare err) {
System.out.println(err); System.out.println(err);
continue; continue;
} catch (Exception err) { } catch (Exception e) {
System.out.println(err); e.printStackTrace();
break;
} }
} }
} }

View File

@ -78,7 +78,7 @@ public class XBoardProtocol {
System.out.println("feature sigint=0 sigterm=0"); System.out.println("feature sigint=0 sigterm=0");
System.out.println("feature usermove=1"); //sends moves like 'usermove e2e4' System.out.println("feature usermove=1"); //sends moves like 'usermove e2e4'
System.out.println("feature variants=\"suicide\""); System.out.println("feature variants=\"suicide\"");
System.out.println("feature time=0 draw=0 reuse=0 analyse=0 colors=0"); System.out.println("feature time=0 draw=0 reuse=0 analyze=0 colors=0");
System.out.println("feature done=1"); System.out.println("feature done=1");
if (SuicideChess.ASCII_GAME) if (SuicideChess.ASCII_GAME)
System.out.println(); System.out.println();