// returns standing pat (static exchange evalutation) score of specified capturing move public static int StaticExchangeEvaluate(ChessMove move, int player) { // variables to track loss values int white_loss = 0, black_loss = 0, next_loss = 0; int wKing_loss = 0, bKing_loss = 0; // flags to check if either king is participating in attack bool wKingAttack = false, bKingAttack = false; // get current occupied BitBoard UInt64 occupied = AI.board.occupied_squares; // get target square of attack uint target = move.GetToSq(); // add piece on target square to color's material loss if (ChessBoard.GetPieceColor(move.GetCapture()) == ChessBoard.WHITE) { white_loss += Score.GetPieceValue(move.GetCapture()); } else if (ChessBoard.GetPieceColor(move.GetCapture()) == ChessBoard.BLACK) { black_loss += Score.GetPieceValue(move.GetCapture()); } // set next loss value equal to value of piece making initial capture next_loss = Score.GetPieceValue(move.GetPiece()); // remove piece making capture from occupied BitBoard occupied ^= ChessBoard.SQUARES[move.GetFromSq()]; // keep track of next player to move int playerToMove = AI.GetOtherPlayer(player); // loop until no more pieces are attacking the target square while (true) { // if either king is participating in an attack illegally, undo last capture, break loop if (wKingAttack && playerToMove == ChessBoard.WHITE) { black_loss -= wKing_loss; break; } else if (bKingAttack && playerToMove == ChessBoard.BLACK) { white_loss -= bKing_loss; break; } // reset attackers BitBoard UInt64 attackers = occupied; // check for attacking pieces of player to move if (playerToMove == ChessBoard.WHITE) { //--------------------// // WHITE PAWNS (NP) // //--------------------// // check for non-promoting white pawns if (ChessMove.GetRank(target) != 7) { // get all non-promoting white pawns attacking target square attackers = occupied & (ChessBoard.PAWN_CAPTURES[target] >> 16) & AI.board.white_pawn; // if attacking piece exists, update black loss, next loss, and occupied BitBoard; repeat loop if (attackers != ChessBoard.EMPTY_BOARD) { // update loss values black_loss += next_loss; next_loss = Score.GetPieceValue(ChessBoard.W_PAWN); // update occupied BitBoard occupied ^= ChessBoard.GetFirstBit(attackers); // switch player to move playerToMove = AI.GetOtherPlayer(playerToMove); // restart loop continue; } } //--------------------// // WHITE KNIGHTS // //--------------------// // get all white knights attacking target square attackers = occupied & (MoveGen.GetKnightMoves(target, occupied)) & AI.board.white_knight; // if attacking piece exists, update black loss, next loss, and occupied BitBoard; repeat loop if (attackers != ChessBoard.EMPTY_BOARD) { // update loss values black_loss += next_loss; next_loss = Score.GetPieceValue(ChessBoard.W_KNIGHT); // update occupied BitBoard occupied ^= ChessBoard.GetFirstBit(attackers); // switch player to move playerToMove = AI.GetOtherPlayer(playerToMove); // restart loop continue; } //--------------------// // WHITE BISHOPS // //--------------------// // get all white bishops attacking target square attackers = occupied & (MoveGen.GetBishopMoves(target, occupied, occupied)) & AI.board.white_bishop; // if attacking piece exists, update black loss, next loss, and occupied BitBoard; repeat loop if (attackers != ChessBoard.EMPTY_BOARD) { // update loss values black_loss += next_loss; next_loss = Score.GetPieceValue(ChessBoard.W_BISHOP); // update occupied BitBoard occupied ^= ChessBoard.GetFirstBit(attackers); // switch player to move playerToMove = AI.GetOtherPlayer(playerToMove); // restart loop continue; } //--------------------// // WHITE ROOKS // //--------------------// // get all white rooks attacking target square attackers = occupied & (MoveGen.GetRookMoves(target, occupied, occupied)) & AI.board.white_rook; // if attacking piece exists, update black loss, next loss, and occupied BitBoard; repeat loop if (attackers != ChessBoard.EMPTY_BOARD) { // update loss values black_loss += next_loss; next_loss = Score.GetPieceValue(ChessBoard.W_ROOK); // update occupied BitBoard occupied ^= ChessBoard.GetFirstBit(attackers); // switch player to move playerToMove = AI.GetOtherPlayer(playerToMove); // restart loop continue; } //--------------------// // WHITE PAWNS (P) // //--------------------// // check for promoting white pawns if (ChessMove.GetRank(target) == 7) { // get all promoting white pawns attacking target square attackers = occupied & (ChessBoard.PAWN_CAPTURES[target - 16]) & AI.board.white_pawn; // if attacking piece exists, update black loss, next loss, and occupied BitBoard; repeat loop if (attackers != ChessBoard.EMPTY_BOARD) { // update loss values black_loss += next_loss; next_loss = Score.GetPieceValue(ChessBoard.W_QUEEN) - Score.GetPieceValue(ChessBoard.W_PAWN); // update occupied BitBoard occupied ^= ChessBoard.GetFirstBit(attackers); // switch player to move playerToMove = AI.GetOtherPlayer(playerToMove); // restart loop continue; } } //--------------------// // WHITE QUEENS // //--------------------// // get all white queens attacking target square attackers = occupied & (MoveGen.GetQueenMoves(target, occupied, occupied)) & AI.board.white_queen; // if attacking piece exists, update black loss, next loss, and occupied BitBoard; repeat loop if (attackers != ChessBoard.EMPTY_BOARD) { // update loss values black_loss += next_loss; next_loss = Score.GetPieceValue(ChessBoard.W_QUEEN); // update occupied BitBoard occupied ^= ChessBoard.GetFirstBit(attackers); // switch player to move playerToMove = AI.GetOtherPlayer(playerToMove); // restart loop continue; } //--------------------// // WHITE KING // //--------------------// // get white king attacking target square attackers = occupied & (MoveGen.GetKingMoves(target, occupied)) & AI.board.white_king; // if attacking piece exists, update black loss, next loss, and occupied BitBoard; repeat loop if (attackers != ChessBoard.EMPTY_BOARD) { // update loss values black_loss += next_loss; wKing_loss = next_loss; // set white king attack flag wKingAttack = true; // update occupied BitBoard occupied ^= ChessBoard.GetFirstBit(attackers); // switch player to move playerToMove = AI.GetOtherPlayer(playerToMove); // restart loop continue; } } else if (playerToMove == ChessBoard.BLACK) { //--------------------// // BLACK PAWNS (NP) // //--------------------// // check for non-promoting black pawns if (ChessMove.GetRank(target) != 0) { // get all non-promoting white pawns attacking target square attackers = occupied & (ChessBoard.PAWN_CAPTURES[target]) & AI.board.black_pawn; // if attacking piece exists, update white loss, next loss, and occupied BitBoard; repeat loop if (attackers != ChessBoard.EMPTY_BOARD) { // update loss values white_loss += next_loss; next_loss = Score.GetPieceValue(ChessBoard.B_PAWN); // update occupied BitBoard occupied ^= ChessBoard.GetFirstBit(attackers); // switch player to move playerToMove = AI.GetOtherPlayer(playerToMove); // restart loop continue; } } //--------------------// // BLACK KNIGHTS // //--------------------// // get all black knights attacking target square attackers = occupied & (MoveGen.GetKnightMoves(target, occupied)) & AI.board.black_knight; // if attacking piece exists, update white loss, next loss, and occupied BitBoard; repeat loop if (attackers != ChessBoard.EMPTY_BOARD) { // update loss values white_loss += next_loss; next_loss = Score.GetPieceValue(ChessBoard.B_KNIGHT); // update occupied BitBoard occupied ^= ChessBoard.GetFirstBit(attackers); // switch player to move playerToMove = AI.GetOtherPlayer(playerToMove); // restart loop continue; } //--------------------// // BLACK BISHOPS // //--------------------// // get all black bishops attacking target square attackers = occupied & (MoveGen.GetBishopMoves(target, occupied, occupied)) & AI.board.black_bishop; // if attacking piece exists, update white loss, next loss, and occupied BitBoard; repeat loop if (attackers != ChessBoard.EMPTY_BOARD) { // update loss values white_loss += next_loss; next_loss = Score.GetPieceValue(ChessBoard.B_BISHOP); // update occupied BitBoard occupied ^= ChessBoard.GetFirstBit(attackers); // switch player to move playerToMove = AI.GetOtherPlayer(playerToMove); // restart loop continue; } //--------------------// // BLACK ROOKS // //--------------------// // get all black rooks attacking target square attackers = occupied & (MoveGen.GetRookMoves(target, occupied, occupied)) & AI.board.black_rook; // if attacking piece exists, update white loss, next loss, and occupied BitBoard; repeat loop if (attackers != ChessBoard.EMPTY_BOARD) { // update loss values white_loss += next_loss; next_loss = Score.GetPieceValue(ChessBoard.B_ROOK); // update occupied BitBoard occupied ^= ChessBoard.GetFirstBit(attackers); // switch player to move playerToMove = AI.GetOtherPlayer(playerToMove); // restart loop continue; } //--------------------// // BLACK PAWNS (P) // //--------------------// // check for promoting black pawns if (ChessMove.GetRank(target) == 0) { // get all promoting black pawns attacking target square attackers = occupied & (ChessBoard.PAWN_CAPTURES[target]) & AI.board.black_pawn; // if attacking piece exists, update white loss, next loss, and occupied BitBoard; repeat loop if (attackers != ChessBoard.EMPTY_BOARD) { // update loss values white_loss += next_loss; next_loss = Score.GetPieceValue(ChessBoard.B_QUEEN) - Score.GetPieceValue(ChessBoard.B_PAWN); // update occupied BitBoard occupied ^= ChessBoard.GetFirstBit(attackers); // switch player to move playerToMove = AI.GetOtherPlayer(playerToMove); // restart loop continue; } } //--------------------// // BLACK QUEENS // //--------------------// // get all black queens attacking target square attackers = occupied & (MoveGen.GetQueenMoves(target, occupied, occupied)) & AI.board.black_queen; // if attacking piece exists, update white loss, next loss, and occupied BitBoard; repeat loop if (attackers != ChessBoard.EMPTY_BOARD) { // update loss values white_loss += next_loss; next_loss = Score.GetPieceValue(ChessBoard.B_QUEEN); // update occupied BitBoard occupied ^= ChessBoard.GetFirstBit(attackers); // switch player to move playerToMove = AI.GetOtherPlayer(playerToMove); // restart loop continue; } //--------------------// // BLACK KING // //--------------------// // get black king attacking target square attackers = occupied & (MoveGen.GetKingMoves(target, occupied)) & AI.board.black_king; // if attacking piece exists, update white loss, next loss, and occupied BitBoard; repeat loop if (attackers != ChessBoard.EMPTY_BOARD) { // update loss values white_loss += next_loss; bKing_loss = next_loss; // set white king attack flag bKingAttack = true; // update occupied BitBoard occupied ^= ChessBoard.GetFirstBit(attackers); // switch player to move playerToMove = AI.GetOtherPlayer(playerToMove); // restart loop continue; } } // no more attacking pieces - break loop break; } // return net standing pat score based on player color if (player == ChessBoard.WHITE) { return(black_loss - white_loss); } else if (player == ChessBoard.BLACK) { return(white_loss - black_loss); } // something went wrong... return(-1); }