Version 1.0.2
============= Corrected a major but in move ordering and a major bug in the evaluation function.
This commit is contained in:
@ -92,8 +92,11 @@ public class Board {
|
||||
private int[] numberOfPieces;
|
||||
//the value of each piece (used for the evaluation function)
|
||||
|
||||
private int boardValue = 0; //evaluation of the board value
|
||||
|
||||
//boardValue
|
||||
private int boardValue = 0; //= mobilityValue+pieceValue except for wining and draw positions
|
||||
private int mobilityValue = 0;
|
||||
private int pieceValue = 0;
|
||||
|
||||
private int currentPlayer; //color of the current player.
|
||||
|
||||
//starts at 1 and increment after each of black's move
|
||||
@ -176,6 +179,9 @@ public class Board {
|
||||
this.halfmoveClock = bitboard.halfmoveClock;
|
||||
|
||||
this.boardValue = bitboard.boardValue;
|
||||
this.pieceValue = bitboard.pieceValue;
|
||||
this.mobilityValue = bitboard.mobilityValue;
|
||||
|
||||
this.bitBoards = new long[NB_OF_BITBOARDS];
|
||||
for (int i=0; i<NB_OF_BITBOARDS; i++) {
|
||||
this.bitBoards[i] = bitboard.bitBoards[i];
|
||||
@ -594,7 +600,6 @@ public class Board {
|
||||
return Rules.getLegalMovesNonCapture().size()*ConfigFile.getPrimaryMobilityValueMidgame();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private void evaluateNewBoardValue (Move move) throws NotAValidSquare {
|
||||
|
||||
@ -603,41 +608,83 @@ public class Board {
|
||||
boardValue = BLACK_WINS;
|
||||
} else if (numberOfPieces[Piece.WHITE] == 0){
|
||||
boardValue = WHITE_WINS;
|
||||
} else {
|
||||
//this is a very very basic evaluation function that will be changed.
|
||||
//boardValue = numberOfBlackPieces - numberOfWhitePieces;
|
||||
boardValue = 0;
|
||||
if((numberOfPieces[Piece.BLACK_PAWN] > ConfigFile.getEndGamePawns()) && (numberOfPieces[Piece.WHITE_PAWN] > ConfigFile.getEndGamePawns())
|
||||
&& (numberOfPieces[Piece.BLACK_PIECES] > ConfigFile.getEndGamePieces()) && (numberOfPieces[Piece.WHITE_PIECES] > ConfigFile.getEndGamePieces()) ) {
|
||||
//System.out.println("Playing midgame");
|
||||
/*for (int i = Piece.OFFSET; i<=Piece.MAX_PIECE_NUMBER; i++) {
|
||||
boardValue += numberOfPieces[i]*Piece.PIECE_VALUE_MIDGAME[i];
|
||||
}*/
|
||||
for(int squareNb = 0; squareNb<NB_OF_SQUARES; squareNb++) {
|
||||
Piece pieceOnSquare = getPiece(new Square(squareNb));
|
||||
if(pieceOnSquare.getPieceNumber()!=Piece.NONE) {
|
||||
//System.out.println(SQUARE_WEIGHT[squareNb]);
|
||||
boardValue += ConfigFile.getSquareWeightMidgame()[squareNb]*
|
||||
ConfigFile.getPieceValuesMidgame()[pieceOnSquare.getPieceNumber()];
|
||||
}
|
||||
}
|
||||
boardValue += ((mobilityMidgame(Piece.WHITE)-mobilityMidgame(Piece.BLACK)));
|
||||
} else {
|
||||
//System.out.println("Playing endgame");
|
||||
/*for (int i = Piece.OFFSET; i<=Piece.MAX_PIECE_NUMBER; i++) {
|
||||
boardValue += numberOfPieces[i]*Piece.PIECE_VALUE_ENDGAME[i];
|
||||
}*/
|
||||
for(int squareNb = 0; squareNb<NB_OF_SQUARES; squareNb++) {
|
||||
Piece pieceOnSquare = getPiece(new Square(squareNb));
|
||||
if(pieceOnSquare.getPieceNumber()!=Piece.NONE) {
|
||||
//System.out.println(SQUARE_WEIGHT[squareNb]);
|
||||
boardValue += ConfigFile.getSquareWeightEndgame()[squareNb]*
|
||||
ConfigFile.getPieceValuesEndgame()[pieceOnSquare.getPieceNumber()];
|
||||
}
|
||||
}
|
||||
boardValue += ((mobilityEndgame(Piece.WHITE)-mobilityEndgame(Piece.BLACK)));
|
||||
}
|
||||
}
|
||||
//this is a very very basic evaluation function that will be changed.
|
||||
//boardValue = numberOfBlackPieces - numberOfWhitePieces;
|
||||
boardValue = 0;
|
||||
if((numberOfPieces[Piece.BLACK_PAWN] > ConfigFile.getEndGamePawns()) && (numberOfPieces[Piece.WHITE_PAWN] > ConfigFile.getEndGamePawns())
|
||||
&& (numberOfPieces[Piece.BLACK_PIECES] > ConfigFile.getEndGamePieces()) && (numberOfPieces[Piece.WHITE_PIECES] > ConfigFile.getEndGamePieces()) ) {
|
||||
//System.out.println("Playing midgame");
|
||||
/*for (int i = Piece.OFFSET; i<=Piece.MAX_PIECE_NUMBER; i++) {
|
||||
boardValue += numberOfPieces[i]*Piece.PIECE_VALUE_MIDGAME[i];
|
||||
}*/
|
||||
|
||||
/*
|
||||
for(int squareNb = 0; squareNb<NB_OF_SQUARES; squareNb++) {
|
||||
Piece pieceOnSquare = getPiece(new Square(squareNb));
|
||||
if(pieceOnSquare.getPieceNumber()!=Piece.NONE) {
|
||||
//System.out.println(SQUARE_WEIGHT[squareNb]);
|
||||
boardValue += ConfigFile.getSquareWeightMidgame()[squareNb]*
|
||||
ConfigFile.getPieceValuesMidgame()[pieceOnSquare.getPieceNumber()];
|
||||
}
|
||||
}
|
||||
}*/
|
||||
|
||||
//update the board value : remove the value of the square the piece comes from and add the value
|
||||
//of the square the piece goes to
|
||||
pieceValue += (
|
||||
ConfigFile.getSquareWeightMidgame()[squareToBitBoardSquare(move.toSquare())]
|
||||
- ConfigFile.getSquareWeightMidgame()[squareToBitBoardSquare(move.fromSquare())]
|
||||
)*ConfigFile.getPieceValuesMidgame()[move.getMovingPiece().getPieceNumber()];
|
||||
//if there is a capture also remove the value of the sqare the piece was captured
|
||||
if (move.isCaptureMove()) {
|
||||
if (move.isEnPassant()) {
|
||||
pieceValue -= ConfigFile.getSquareWeightMidgame()[squareToBitBoardSquare(move.getEnPassantSquare())]
|
||||
*ConfigFile.getPieceValuesMidgame()[move.getCapturedPiece().getPieceNumber()];
|
||||
} else {
|
||||
pieceValue -= ConfigFile.getSquareWeightMidgame()[squareToBitBoardSquare(move.toSquare())]
|
||||
*ConfigFile.getPieceValuesMidgame()[move.getCapturedPiece().getPieceNumber()];
|
||||
}
|
||||
|
||||
}
|
||||
if(SuicideChess.USE_MOBILITY) {
|
||||
mobilityValue = ((mobilityMidgame(Piece.WHITE)-mobilityMidgame(Piece.BLACK)));
|
||||
}
|
||||
boardValue = pieceValue + mobilityValue;
|
||||
} else {
|
||||
//System.out.println("Playing endgame");
|
||||
/*for (int i = Piece.OFFSET; i<=Piece.MAX_PIECE_NUMBER; i++) {
|
||||
boardValue += numberOfPieces[i]*Piece.PIECE_VALUE_ENDGAME[i];
|
||||
}*/
|
||||
|
||||
/*
|
||||
for(int squareNb = 0; squareNb<NB_OF_SQUARES; squareNb++) {
|
||||
Piece pieceOnSquare = getPiece(new Square(squareNb));
|
||||
if(pieceOnSquare.getPieceNumber()!=Piece.NONE) {
|
||||
//System.out.println(SQUARE_WEIGHT[squareNb]);
|
||||
boardValue += ConfigFile.getSquareWeightEndgame()[squareNb]*
|
||||
ConfigFile.getPieceValuesEndgame()[pieceOnSquare.getPieceNumber()];
|
||||
}
|
||||
}*/
|
||||
|
||||
pieceValue += (
|
||||
ConfigFile.getSquareWeightEndgame()[squareToBitBoardSquare(move.toSquare())]
|
||||
- ConfigFile.getSquareWeightEndgame()[squareToBitBoardSquare(move.fromSquare())]
|
||||
)*ConfigFile.getPieceValuesEndgame()[move.getMovingPiece().getPieceNumber()];
|
||||
if (move.isCaptureMove()) {
|
||||
if (move.isEnPassant()) {
|
||||
pieceValue -= ConfigFile.getSquareWeightEndgame()[squareToBitBoardSquare(move.getEnPassantSquare())]
|
||||
*ConfigFile.getPieceValuesEndgame()[move.getCapturedPiece().getPieceNumber()];
|
||||
} else {
|
||||
pieceValue -= ConfigFile.getSquareWeightMidgame()[squareToBitBoardSquare(move.toSquare())]
|
||||
*ConfigFile.getPieceValuesEndgame()[move.getCapturedPiece().getPieceNumber()];
|
||||
}
|
||||
|
||||
}
|
||||
if(SuicideChess.USE_MOBILITY) {
|
||||
mobilityValue = ((mobilityEndgame(Piece.WHITE)-mobilityEndgame(Piece.BLACK)));
|
||||
}
|
||||
boardValue = pieceValue + mobilityValue;
|
||||
}
|
||||
if (!Rules.isThereALegalMovesForPlayer(this)) {
|
||||
if (currentPlayer==Piece.WHITE) {
|
||||
|
@ -175,6 +175,8 @@ public class ComputerPlayer {
|
||||
}
|
||||
}
|
||||
|
||||
thinkingBeginingTime = new Date();
|
||||
nodesSearched=0;
|
||||
//alpha beta pruning.
|
||||
ReturnWrapper bestScore = AlphaBeta(bitboard, 0, SuicideChess.PRINCIPAL_VARIATION_FIRST
|
||||
, maxDepth, Board.MIN_VALUE, Board.MAX_VALUE);
|
||||
@ -300,7 +302,31 @@ public class ComputerPlayer {
|
||||
String bestVariationSoFar="";
|
||||
ReturnWrapper returnValue;
|
||||
if (SuicideChess.MOVE_ORDERING) {
|
||||
Collections.sort(allLegalMoves,new MoveCompare(bitboard));
|
||||
/* DEBUG
|
||||
if(currentDepth==0) {
|
||||
String debug = "";
|
||||
for (int i=0; i<allLegalMoves.size(); i++) {
|
||||
Board bitboardCopy = new Board(bitboard);
|
||||
bitboardCopy.doMove(allLegalMoves.get(i));
|
||||
debug += allLegalMoves.get(i).toString()+bitboardCopy.getBoardValue()+" ";
|
||||
}
|
||||
System.out.println(debug);
|
||||
}
|
||||
*/
|
||||
|
||||
Collections.sort(allLegalMoves,new MoveCompare(bitboard));
|
||||
|
||||
/* DEBUG
|
||||
if(currentDepth==0) {
|
||||
String debug = "";
|
||||
for (int i=0; i<allLegalMoves.size(); i++) {
|
||||
Board bitboardCopy = new Board(bitboard);
|
||||
bitboardCopy.doMove(allLegalMoves.get(i));
|
||||
debug += allLegalMoves.get(i).toString()+bitboardCopy.getBoardValue()+" ";
|
||||
}
|
||||
System.out.println(debug);
|
||||
}
|
||||
*/
|
||||
}
|
||||
if (bitboard.getCurrentPlayer()==Piece.BLACK) {
|
||||
bestScoreSoFar=Board.MAX_VALUE; //black tries to minimise
|
||||
|
@ -25,9 +25,11 @@ class MoveCompare implements Comparator<Move> {
|
||||
public MoveCompare(Board bitboard) {
|
||||
this.bitboard = bitboard;
|
||||
if(this.bitboard.getCurrentPlayer()==Piece.BLACK) {
|
||||
sortOrder= +1;
|
||||
// low scores are considered "smaller" than high ones and thus will be first after ordering
|
||||
sortOrder= -1;
|
||||
} else {
|
||||
sortOrder= -1;
|
||||
// high scores are consideres "smaller" than low ones
|
||||
sortOrder= +1;
|
||||
}
|
||||
}
|
||||
|
||||
@ -42,9 +44,9 @@ class MoveCompare implements Comparator<Move> {
|
||||
} catch (NotAValidSquare e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
if(oneBoardCopy.getBoardValue()>anotherBoardCopy.getBoardValue()) {
|
||||
if(oneBoardCopy.getBoardValue()<anotherBoardCopy.getBoardValue()) {
|
||||
return sortOrder;
|
||||
} else if (oneBoardCopy.getBoardValue()>anotherBoardCopy.getBoardValue()) {
|
||||
} else if (oneBoardCopy.getBoardValue()==anotherBoardCopy.getBoardValue()) {
|
||||
return 0;
|
||||
}
|
||||
return -sortOrder;
|
||||
|
@ -327,6 +327,69 @@ public class Rules {
|
||||
} //end case
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Computes the mobility of a piece on a given {@link Square}
|
||||
* according to the current status of the {@link Board}
|
||||
* @param fromSquare The square from which the move must start
|
||||
* @param board The current board position.
|
||||
* @return boolean Stating if there is or not a legal move.
|
||||
* @throws NotAValidSquare If the program throws this exception then there is a bug.
|
||||
* @throws UnexpectedError This should never happen.
|
||||
* @see Square
|
||||
* @see Board
|
||||
*/
|
||||
/*public static int mobilityEndgame(Square fromSquare, Board board) throws NotAValidSquare {
|
||||
legalMovesNonCapture = new ArrayList<Move>();
|
||||
legalMovesCapture = new ArrayList<Move>();
|
||||
legalMovesFromSquare(fromSquare,board);
|
||||
|
||||
int mobility;
|
||||
if (legalMovesCapture.size()!=0) {
|
||||
mobility = legalMovesCapture.size()*ConfigFile.getPrimaryMobilityValueEndgame()
|
||||
+legalMovesNonCapture.size()*ConfigFile.getScondaryMobilityValueEndgame();
|
||||
} else {
|
||||
mobility = legalMovesNonCapture.size()*ConfigFile.getPrimaryMobilityValueEndgame();
|
||||
}
|
||||
|
||||
if (board.getPiece(fromSquare).getColor()==Piece.BLACK) {
|
||||
return -mobility;
|
||||
} else {
|
||||
return mobility;
|
||||
}
|
||||
}*/
|
||||
|
||||
/**
|
||||
* Computes the mobility of a piece on a given {@link Square}
|
||||
* according to the current status of the {@link Board}
|
||||
* @param fromSquare The square from which the move must start
|
||||
* @param board The current board position.
|
||||
* @return boolean Stating if there is or not a legal move.
|
||||
* @throws NotAValidSquare If the program throws this exception then there is a bug.
|
||||
* @throws UnexpectedError This should never happen.
|
||||
* @see Square
|
||||
* @see Board
|
||||
*/
|
||||
/*public static int mobilityMidgame(Square fromSquare, Board board) throws NotAValidSquare {
|
||||
legalMovesNonCapture = new ArrayList<Move>();
|
||||
legalMovesCapture = new ArrayList<Move>();
|
||||
legalMovesFromSquare(fromSquare,board);
|
||||
|
||||
int mobility;
|
||||
if (legalMovesCapture.size()!=0) {
|
||||
mobility = legalMovesCapture.size()*ConfigFile.getPrimaryMobilityValueMidgame()
|
||||
+legalMovesNonCapture.size()*ConfigFile.getPrimaryMobilityValueMidgame();
|
||||
} else {
|
||||
mobility = legalMovesNonCapture.size()*ConfigFile.getPrimaryMobilityValueMidgame();
|
||||
}
|
||||
if (board.getPiece(fromSquare).getColor()==Piece.BLACK) {
|
||||
return -mobility;
|
||||
} else {
|
||||
return mobility;
|
||||
}
|
||||
}*/
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* This function return the current status of the ArrayList<Move> of all legal {@link Move}
|
||||
|
@ -34,6 +34,11 @@ public class SuicideChess {
|
||||
*/
|
||||
public static final boolean SQUARE_CHECK_INVALID = true;
|
||||
|
||||
/**
|
||||
* Use mobility in evaluation function (slows the program down a lot)
|
||||
*/
|
||||
public static final boolean USE_MOBILITY = true;
|
||||
|
||||
/**
|
||||
* do move ordering in Alpha-Beta pruning ?
|
||||
*/
|
||||
@ -74,7 +79,7 @@ public class SuicideChess {
|
||||
/**
|
||||
* Adaptative depth -> ie: when only one possible move, don't search. When very few moves, add one to depth.
|
||||
*/
|
||||
public static final boolean ADAPTATIVE_DEPTH = true;
|
||||
public static final boolean ADAPTATIVE_DEPTH = false;
|
||||
|
||||
/**
|
||||
* Adaptative branchin limit
|
||||
@ -89,12 +94,12 @@ public class SuicideChess {
|
||||
/**
|
||||
* Try the primary variation from the earliest iteration first
|
||||
*/
|
||||
public static final boolean PRINCIPAL_VARIATION_FIRST = true;
|
||||
public static final boolean PRINCIPAL_VARIATION_FIRST = false;
|
||||
|
||||
/**
|
||||
* The name to be displayed
|
||||
*/
|
||||
public static final String NAME = "djib's SuShi v1.0.0";
|
||||
public static final String NAME = "djib's SuShi v1.0.2";
|
||||
|
||||
/**
|
||||
* Displays informations in the console.
|
||||
@ -232,6 +237,7 @@ public class SuicideChess {
|
||||
System.out.println("force\t\t\tthe computer will check moves but not play");
|
||||
System.out.println();
|
||||
System.out.println("board\t\t\tdisplays the current status of the board");
|
||||
System.out.println("eval\t\t\tevaluates the current board position");
|
||||
System.out.println("setboard FEN\t\tsets the board according to the FEN position");
|
||||
System.out.println("sd N\t\t\tsets the search depth to n");
|
||||
System.out.println("bk\t\t\tdisplays available openbook moves for current position");
|
||||
@ -258,8 +264,11 @@ public class SuicideChess {
|
||||
try {
|
||||
int problemNb = Integer.parseInt(whatMove.substring(8));
|
||||
bitboard=new Board(SuicideProblems.getProblemNumber(problemNb));
|
||||
if(asciiGame)
|
||||
if(asciiGame) {
|
||||
bitboard.display();
|
||||
displayPlayer(bitboard);
|
||||
}
|
||||
addPlayedPosition(bitboard);
|
||||
} catch (NumberFormatException e) {
|
||||
System.out.println("Not a valid number: "+ whatMove.substring(8));
|
||||
}
|
||||
@ -277,8 +286,10 @@ public class SuicideChess {
|
||||
} else if (whatMove.startsWith("asciiplay")) {
|
||||
asciiGame=false;
|
||||
} else if ((whatMove.startsWith("board"))) {
|
||||
bitboard.display();
|
||||
} else {
|
||||
bitboard.display();
|
||||
} else if ((whatMove.startsWith("eval"))) {
|
||||
System.out.println(bitboard.getBoardValue());
|
||||
}else {
|
||||
int xBoardCommand = XBoardProtocol.getCommand(whatMove);
|
||||
|
||||
switch (xBoardCommand) {
|
||||
@ -314,8 +325,10 @@ public class SuicideChess {
|
||||
OpeningBook.reset();
|
||||
computerPlaying = true; //the computer does not play in foce mode.
|
||||
|
||||
if(playInACSII())
|
||||
if(playInACSII()) {
|
||||
bitboard.display();
|
||||
displayPlayer(bitboard);
|
||||
}
|
||||
//System.out.println("variant suicide");
|
||||
break;
|
||||
case XBoardProtocol.HINT:
|
||||
@ -334,6 +347,7 @@ public class SuicideChess {
|
||||
bitboard=new Board(removePlayedPosition());
|
||||
if (asciiGame) {
|
||||
bitboard.display();
|
||||
displayPlayer(bitboard);
|
||||
}
|
||||
openingPhase = false; //due to the way I implemented the opening book
|
||||
break;
|
||||
@ -345,9 +359,11 @@ public class SuicideChess {
|
||||
break;
|
||||
case XBoardProtocol.SETBOARD:
|
||||
bitboard=new Board(whatMove.substring(9));
|
||||
addPlayedPosition(bitboard);
|
||||
openingPhase = false;
|
||||
if(asciiGame)
|
||||
bitboard.display();
|
||||
displayPlayer(bitboard);
|
||||
break;
|
||||
case XBoardProtocol.SETPLY:
|
||||
try{
|
||||
|
Reference in New Issue
Block a user