Version 1.0.2

=============
Corrected a major but in move ordering
and a major bug in the evaluation function.
This commit is contained in:
2006-07-16 17:17:40 +00:00
parent 399985789e
commit 9c4916fb1b
5 changed files with 203 additions and 49 deletions

View File

@ -92,7 +92,10 @@ public class Board {
private int[] numberOfPieces; private int[] numberOfPieces;
//the value of each piece (used for the evaluation function) //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. private int currentPlayer; //color of the current player.
@ -176,6 +179,9 @@ public class Board {
this.halfmoveClock = bitboard.halfmoveClock; this.halfmoveClock = bitboard.halfmoveClock;
this.boardValue = bitboard.boardValue; this.boardValue = bitboard.boardValue;
this.pieceValue = bitboard.pieceValue;
this.mobilityValue = bitboard.mobilityValue;
this.bitBoards = new long[NB_OF_BITBOARDS]; this.bitBoards = new long[NB_OF_BITBOARDS];
for (int i=0; i<NB_OF_BITBOARDS; i++) { for (int i=0; i<NB_OF_BITBOARDS; i++) {
this.bitBoards[i] = bitboard.bitBoards[i]; this.bitBoards[i] = bitboard.bitBoards[i];
@ -595,7 +601,6 @@ public class Board {
} }
} }
private void evaluateNewBoardValue (Move move) throws NotAValidSquare { private void evaluateNewBoardValue (Move move) throws NotAValidSquare {
if (move.isCaptureMove()) { if (move.isCaptureMove()) {
@ -603,7 +608,8 @@ public class Board {
boardValue = BLACK_WINS; boardValue = BLACK_WINS;
} else if (numberOfPieces[Piece.WHITE] == 0){ } else if (numberOfPieces[Piece.WHITE] == 0){
boardValue = WHITE_WINS; boardValue = WHITE_WINS;
} else { }
}
//this is a very very basic evaluation function that will be changed. //this is a very very basic evaluation function that will be changed.
//boardValue = numberOfBlackPieces - numberOfWhitePieces; //boardValue = numberOfBlackPieces - numberOfWhitePieces;
boardValue = 0; boardValue = 0;
@ -613,6 +619,8 @@ public class Board {
/*for (int i = Piece.OFFSET; i<=Piece.MAX_PIECE_NUMBER; i++) { /*for (int i = Piece.OFFSET; i<=Piece.MAX_PIECE_NUMBER; i++) {
boardValue += numberOfPieces[i]*Piece.PIECE_VALUE_MIDGAME[i]; boardValue += numberOfPieces[i]*Piece.PIECE_VALUE_MIDGAME[i];
}*/ }*/
/*
for(int squareNb = 0; squareNb<NB_OF_SQUARES; squareNb++) { for(int squareNb = 0; squareNb<NB_OF_SQUARES; squareNb++) {
Piece pieceOnSquare = getPiece(new Square(squareNb)); Piece pieceOnSquare = getPiece(new Square(squareNb));
if(pieceOnSquare.getPieceNumber()!=Piece.NONE) { if(pieceOnSquare.getPieceNumber()!=Piece.NONE) {
@ -620,13 +628,36 @@ public class Board {
boardValue += ConfigFile.getSquareWeightMidgame()[squareNb]* boardValue += ConfigFile.getSquareWeightMidgame()[squareNb]*
ConfigFile.getPieceValuesMidgame()[pieceOnSquare.getPieceNumber()]; 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()];
} }
boardValue += ((mobilityMidgame(Piece.WHITE)-mobilityMidgame(Piece.BLACK)));
}
if(SuicideChess.USE_MOBILITY) {
mobilityValue = ((mobilityMidgame(Piece.WHITE)-mobilityMidgame(Piece.BLACK)));
}
boardValue = pieceValue + mobilityValue;
} else { } else {
//System.out.println("Playing endgame"); //System.out.println("Playing endgame");
/*for (int i = Piece.OFFSET; i<=Piece.MAX_PIECE_NUMBER; i++) { /*for (int i = Piece.OFFSET; i<=Piece.MAX_PIECE_NUMBER; i++) {
boardValue += numberOfPieces[i]*Piece.PIECE_VALUE_ENDGAME[i]; boardValue += numberOfPieces[i]*Piece.PIECE_VALUE_ENDGAME[i];
}*/ }*/
/*
for(int squareNb = 0; squareNb<NB_OF_SQUARES; squareNb++) { for(int squareNb = 0; squareNb<NB_OF_SQUARES; squareNb++) {
Piece pieceOnSquare = getPiece(new Square(squareNb)); Piece pieceOnSquare = getPiece(new Square(squareNb));
if(pieceOnSquare.getPieceNumber()!=Piece.NONE) { if(pieceOnSquare.getPieceNumber()!=Piece.NONE) {
@ -634,10 +665,26 @@ public class Board {
boardValue += ConfigFile.getSquareWeightEndgame()[squareNb]* boardValue += ConfigFile.getSquareWeightEndgame()[squareNb]*
ConfigFile.getPieceValuesEndgame()[pieceOnSquare.getPieceNumber()]; 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()];
} }
boardValue += ((mobilityEndgame(Piece.WHITE)-mobilityEndgame(Piece.BLACK)));
} }
if(SuicideChess.USE_MOBILITY) {
mobilityValue = ((mobilityEndgame(Piece.WHITE)-mobilityEndgame(Piece.BLACK)));
} }
boardValue = pieceValue + mobilityValue;
} }
if (!Rules.isThereALegalMovesForPlayer(this)) { if (!Rules.isThereALegalMovesForPlayer(this)) {
if (currentPlayer==Piece.WHITE) { if (currentPlayer==Piece.WHITE) {

View File

@ -175,6 +175,8 @@ public class ComputerPlayer {
} }
} }
thinkingBeginingTime = new Date();
nodesSearched=0;
//alpha beta pruning. //alpha beta pruning.
ReturnWrapper bestScore = AlphaBeta(bitboard, 0, SuicideChess.PRINCIPAL_VARIATION_FIRST ReturnWrapper bestScore = AlphaBeta(bitboard, 0, SuicideChess.PRINCIPAL_VARIATION_FIRST
, maxDepth, Board.MIN_VALUE, Board.MAX_VALUE); , maxDepth, Board.MIN_VALUE, Board.MAX_VALUE);
@ -300,7 +302,31 @@ public class ComputerPlayer {
String bestVariationSoFar=""; String bestVariationSoFar="";
ReturnWrapper returnValue; ReturnWrapper returnValue;
if (SuicideChess.MOVE_ORDERING) { if (SuicideChess.MOVE_ORDERING) {
/* 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)); 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) { if (bitboard.getCurrentPlayer()==Piece.BLACK) {
bestScoreSoFar=Board.MAX_VALUE; //black tries to minimise bestScoreSoFar=Board.MAX_VALUE; //black tries to minimise

View File

@ -25,9 +25,11 @@ class MoveCompare implements Comparator<Move> {
public MoveCompare(Board bitboard) { public MoveCompare(Board bitboard) {
this.bitboard = bitboard; this.bitboard = bitboard;
if(this.bitboard.getCurrentPlayer()==Piece.BLACK) { if(this.bitboard.getCurrentPlayer()==Piece.BLACK) {
sortOrder= +1; // low scores are considered "smaller" than high ones and thus will be first after ordering
} else {
sortOrder= -1; sortOrder= -1;
} else {
// high scores are consideres "smaller" than low ones
sortOrder= +1;
} }
} }
@ -42,9 +44,9 @@ class MoveCompare implements Comparator<Move> {
} catch (NotAValidSquare e) { } catch (NotAValidSquare e) {
e.printStackTrace(); e.printStackTrace();
} }
if(oneBoardCopy.getBoardValue()>anotherBoardCopy.getBoardValue()) { if(oneBoardCopy.getBoardValue()<anotherBoardCopy.getBoardValue()) {
return sortOrder; return sortOrder;
} else if (oneBoardCopy.getBoardValue()>anotherBoardCopy.getBoardValue()) { } else if (oneBoardCopy.getBoardValue()==anotherBoardCopy.getBoardValue()) {
return 0; return 0;
} }
return -sortOrder; return -sortOrder;

View File

@ -328,6 +328,69 @@ public class Rules {
} }
/**
* 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} * This function return the current status of the ArrayList<Move> of all legal {@link Move}
* without a capture. * without a capture.

View File

@ -34,6 +34,11 @@ public class SuicideChess {
*/ */
public static final boolean SQUARE_CHECK_INVALID = true; 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 ? * 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. * 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 * Adaptative branchin limit
@ -89,12 +94,12 @@ public class SuicideChess {
/** /**
* Try the primary variation from the earliest iteration first * 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 * 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. * 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("force\t\t\tthe computer will check moves but not play");
System.out.println(); System.out.println();
System.out.println("board\t\t\tdisplays the current status of the board"); 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("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("sd N\t\t\tsets the search depth to n");
System.out.println("bk\t\t\tdisplays available openbook moves for current position"); System.out.println("bk\t\t\tdisplays available openbook moves for current position");
@ -258,8 +264,11 @@ public class SuicideChess {
try { try {
int problemNb = Integer.parseInt(whatMove.substring(8)); int problemNb = Integer.parseInt(whatMove.substring(8));
bitboard=new Board(SuicideProblems.getProblemNumber(problemNb)); bitboard=new Board(SuicideProblems.getProblemNumber(problemNb));
if(asciiGame) if(asciiGame) {
bitboard.display(); bitboard.display();
displayPlayer(bitboard);
}
addPlayedPosition(bitboard);
} catch (NumberFormatException e) { } catch (NumberFormatException e) {
System.out.println("Not a valid number: "+ whatMove.substring(8)); System.out.println("Not a valid number: "+ whatMove.substring(8));
} }
@ -278,7 +287,9 @@ public class SuicideChess {
asciiGame=false; asciiGame=false;
} else if ((whatMove.startsWith("board"))) { } else if ((whatMove.startsWith("board"))) {
bitboard.display(); bitboard.display();
} else { } else if ((whatMove.startsWith("eval"))) {
System.out.println(bitboard.getBoardValue());
}else {
int xBoardCommand = XBoardProtocol.getCommand(whatMove); int xBoardCommand = XBoardProtocol.getCommand(whatMove);
switch (xBoardCommand) { switch (xBoardCommand) {
@ -314,8 +325,10 @@ public class SuicideChess {
OpeningBook.reset(); OpeningBook.reset();
computerPlaying = true; //the computer does not play in foce mode. computerPlaying = true; //the computer does not play in foce mode.
if(playInACSII()) if(playInACSII()) {
bitboard.display(); bitboard.display();
displayPlayer(bitboard);
}
//System.out.println("variant suicide"); //System.out.println("variant suicide");
break; break;
case XBoardProtocol.HINT: case XBoardProtocol.HINT:
@ -334,6 +347,7 @@ public class SuicideChess {
bitboard=new Board(removePlayedPosition()); bitboard=new Board(removePlayedPosition());
if (asciiGame) { if (asciiGame) {
bitboard.display(); bitboard.display();
displayPlayer(bitboard);
} }
openingPhase = false; //due to the way I implemented the opening book openingPhase = false; //due to the way I implemented the opening book
break; break;
@ -345,9 +359,11 @@ public class SuicideChess {
break; break;
case XBoardProtocol.SETBOARD: case XBoardProtocol.SETBOARD:
bitboard=new Board(whatMove.substring(9)); bitboard=new Board(whatMove.substring(9));
addPlayedPosition(bitboard);
openingPhase = false; openingPhase = false;
if(asciiGame) if(asciiGame)
bitboard.display(); bitboard.display();
displayPlayer(bitboard);
break; break;
case XBoardProtocol.SETPLY: case XBoardProtocol.SETPLY:
try{ try{