void EvalKnight(Board b, EvaluationScores v, Position sq, Piece side, ulong[] pawnControl, ulong pinned) { int att = 0; int mob = 0; /************************************************************************** * Collect data about mobility and king attacks. This resembles move * * generation code, except that we are just incrementing the counters * * instead of adding actual moves. * **************************************************************************/ var jumps = BitboardConstants.KnightJumps[sq]; var opponent = side == ChessPiece.White ? b.BlackPieces : b.WhitePieces; var emptyOrOpponent = (b.EmptySquares | opponent) & jumps; var bitboard = 1UL << sq; if ((bitboard & pinned) == 0) { var uncontrolled = emptyOrOpponent & ~pawnControl[side ^ 1]; mob += uncontrolled.PopCount(); } var emptyOrOpponentNearKing = emptyOrOpponent & BitboardConstants.KingExtendedJumps[side ^ 1][b.KingPositions[side ^ 1]]; att += emptyOrOpponentNearKing.PopCount(); /************************************************************************** * Evaluate mobility. We try to do it in such a way that zero represents * * average mobility, but our formula of doing so is a puer guess. * **************************************************************************/ v.mgMob[side] += 4 * (mob - 4); v.egMob[side] += 4 * (mob - 4); /************************************************************************** * Save data about king attacks * **************************************************************************/ if (att > 0) { v.attCnt[side]++; v.attWeight[side] += 2 * att; } /************************************************************************** * Evaluate king tropism * **************************************************************************/ int tropism = getTropism(sq, b.KingPositions[side ^ 1]); v.mgTropism[side] += 3 * tropism; v.egTropism[side] += 3 * tropism; }
public EvaluationService2(EvaluationData evaluationData) { _pawnControl = new ulong[2]; _evaluationScores = new EvaluationScores(); _evaluationData = evaluationData; _evalTable = new EvalHashTable(); _evalTable.SetSize(16 * 1024 * 1024); _pawnTable = new EvalHashTable(); _pawnTable.SetSize(16 * 1024 * 1024); _slideGenerator = new MagicBitboardsService(); _pinDetector = new PinDetector(_slideGenerator); _attacks = new AttacksService(_slideGenerator); }
void printEval(Board b, EvaluationData e, EvaluationScores v, Score score) { var builder = new StringBuilder(); builder.Append("------------------------------------------\n"); builder.Append($"Total value (for side to move): {score}\n"); builder.Append($"Material balance : {b.PieceMaterial[ChessPiece.White] + b.PawnMaterial[ChessPiece.White] - b.PieceMaterial[ChessPiece.Black] - b.PawnMaterial[ChessPiece.Black]} \n"); builder.Append("Material adjustement : "); printEvalFactor(builder, v.adjustMaterial[ChessPiece.White], v.adjustMaterial[ChessPiece.Black]); builder.Append("Mg Piece/square tables : "); printEvalFactor(builder, v.PieceSquaresMidgame[ChessPiece.White], v.PieceSquaresMidgame[ChessPiece.Black]); builder.Append("Eg Piece/square tables : "); printEvalFactor(builder, v.PieceSquaresEndgame[ChessPiece.White], v.PieceSquaresEndgame[ChessPiece.Black]); builder.Append("Mg Mobility : "); printEvalFactor(builder, v.mgMob[ChessPiece.White], v.mgMob[ChessPiece.Black]); builder.Append("Eg Mobility : "); printEvalFactor(builder, v.egMob[ChessPiece.White], v.egMob[ChessPiece.Black]); builder.Append("Mg Tropism : "); printEvalFactor(builder, v.mgTropism[ChessPiece.White], v.mgTropism[ChessPiece.Black]); builder.Append("Eg Tropism : "); printEvalFactor(builder, v.egTropism[ChessPiece.White], v.egTropism[ChessPiece.Black]); //builder.Append("Pawn structure : %d \n", evalPawnStructure()); builder.Append("Blockages : "); printEvalFactor(builder, v.blockages[ChessPiece.White], v.blockages[ChessPiece.Black]); builder.Append("Positional themes : "); printEvalFactor(builder, v.positionalThemes[ChessPiece.White], v.positionalThemes[ChessPiece.Black]); builder.Append("King Shield : "); printEvalFactor(builder, v.kingShield[ChessPiece.White], v.kingShield[ChessPiece.Black]); builder.Append("Tempo : "); if (b.WhiteToMove) { builder.Append(EvaluationData.TEMPO); } else { builder.Append(-EvaluationData.TEMPO); } builder.Append("\n"); builder.Append("------------------------------------------\n"); Console.WriteLine(builder.ToString()); }
void EvalBishop(Board b, EvaluationScores v, Position sq, Piece side, ulong[] pawnControl, ulong pinned) { int att = 0; int mob = 0; /************************************************************************** * Collect data about mobility and king attacks * **************************************************************************/ var slide = _slideGenerator.DiagonalAntidiagonalSlide(b.AllPieces, sq); var opponent = (side == ChessPiece.White ? b.BlackPieces : b.WhitePieces) & slide; var bitboard = 1UL << sq; if ((bitboard & pinned) == 0) { var emptyUncontrolled = b.EmptySquares & ~pawnControl[side ^ 1] & slide; mob += emptyUncontrolled.PopCount(); mob += opponent.PopCount(); } var emptyOrOpponentNearKing = (b.EmptySquares | opponent) & BitboardConstants.KingExtendedJumps[side ^ 1][b.KingPositions[side ^ 1]] & slide; att += emptyOrOpponentNearKing.PopCount(); v.mgMob[side] += 3 * (mob - 7); v.egMob[side] += 3 * (mob - 7); if (att > 0) { v.attCnt[side]++; v.attWeight[side] += 2 * att; } int tropism = getTropism(sq, b.KingPositions[side ^ 1]); v.mgTropism[side] += 2 * tropism; v.egTropism[side] += 1 * tropism; }
void blockedPieces(Board b, EvaluationScores v, int side) { int oppo = side ^ 1; // central pawn blocked, bishop hard to develop if (isPiece(b, side, ChessPiece.Bishop, REL_SQ(side, ChessPosition.C1)) && isPiece(b, side, ChessPiece.Pawn, REL_SQ(side, ChessPosition.D2)) && b.ArrayBoard[REL_SQ(side, ChessPosition.D3)] != ChessPiece.Empty) { v.blockages[side] -= EvaluationData.P_BLOCK_CENTRAL_PAWN; } if (isPiece(b, side, ChessPiece.Bishop, REL_SQ(side, ChessPosition.F1)) && isPiece(b, side, ChessPiece.Pawn, REL_SQ(side, ChessPosition.E2)) && b.ArrayBoard[REL_SQ(side, ChessPosition.E3)] != ChessPiece.Empty) { v.blockages[side] -= EvaluationData.P_BLOCK_CENTRAL_PAWN; } // trapped knight if (isPiece(b, side, ChessPiece.Knight, REL_SQ(side, ChessPosition.A8)) && (isPiece(b, oppo, ChessPiece.Pawn, REL_SQ(side, ChessPosition.A7)) || isPiece(b, oppo, ChessPiece.Pawn, REL_SQ(side, ChessPosition.C7)))) { v.blockages[side] -= EvaluationData.P_KNIGHT_TRAPPED_A8; } if (isPiece(b, side, ChessPiece.Knight, REL_SQ(side, ChessPosition.H8)) && (isPiece(b, oppo, ChessPiece.Pawn, REL_SQ(side, ChessPosition.H7)) || isPiece(b, oppo, ChessPiece.Pawn, REL_SQ(side, ChessPosition.F7)))) { v.blockages[side] -= EvaluationData.P_KNIGHT_TRAPPED_A8; } if (isPiece(b, side, ChessPiece.Knight, REL_SQ(side, ChessPosition.A7)) && isPiece(b, oppo, ChessPiece.Pawn, REL_SQ(side, ChessPosition.A6)) && isPiece(b, oppo, ChessPiece.Pawn, REL_SQ(side, ChessPosition.B7))) { v.blockages[side] -= EvaluationData.P_KNIGHT_TRAPPED_A7; } if (isPiece(b, side, ChessPiece.Knight, REL_SQ(side, ChessPosition.H7)) && isPiece(b, oppo, ChessPiece.Pawn, REL_SQ(side, ChessPosition.H6)) && isPiece(b, oppo, ChessPiece.Pawn, REL_SQ(side, ChessPosition.G7))) { v.blockages[side] -= EvaluationData.P_KNIGHT_TRAPPED_A7; } // knight blocking queenside pawns if (isPiece(b, side, ChessPiece.Knight, REL_SQ(side, ChessPosition.C3)) && isPiece(b, side, ChessPiece.Pawn, REL_SQ(side, ChessPosition.C2)) && isPiece(b, side, ChessPiece.Pawn, REL_SQ(side, ChessPosition.D4)) && !isPiece(b, side, ChessPiece.Pawn, REL_SQ(side, ChessPosition.E4))) { v.blockages[side] -= EvaluationData.P_C3_KNIGHT; } // trapped bishop if (isPiece(b, side, ChessPiece.Bishop, REL_SQ(side, ChessPosition.A7)) && isPiece(b, oppo, ChessPiece.Pawn, REL_SQ(side, ChessPosition.B6))) { v.blockages[side] -= EvaluationData.P_BISHOP_TRAPPED_A7; } if (isPiece(b, side, ChessPiece.Bishop, REL_SQ(side, ChessPosition.H7)) && isPiece(b, oppo, ChessPiece.Pawn, REL_SQ(side, ChessPosition.G6))) { v.blockages[side] -= EvaluationData.P_BISHOP_TRAPPED_A7; } if (isPiece(b, side, ChessPiece.Bishop, REL_SQ(side, ChessPosition.B8)) && isPiece(b, oppo, ChessPiece.Pawn, REL_SQ(side, ChessPosition.C7))) { v.blockages[side] -= EvaluationData.P_BISHOP_TRAPPED_A7; } if (isPiece(b, side, ChessPiece.Bishop, REL_SQ(side, ChessPosition.G8)) && isPiece(b, oppo, ChessPiece.Pawn, REL_SQ(side, ChessPosition.F7))) { v.blockages[side] -= EvaluationData.P_BISHOP_TRAPPED_A7; } if (isPiece(b, side, ChessPiece.Bishop, REL_SQ(side, ChessPosition.A6)) && isPiece(b, oppo, ChessPiece.Pawn, REL_SQ(side, ChessPosition.B5))) { v.blockages[side] -= EvaluationData.P_BISHOP_TRAPPED_A6; } if (isPiece(b, side, ChessPiece.Bishop, REL_SQ(side, ChessPosition.H6)) && isPiece(b, oppo, ChessPiece.Pawn, REL_SQ(side, ChessPosition.G5))) { v.blockages[side] -= EvaluationData.P_BISHOP_TRAPPED_A6; } // bishop on initial sqare supporting castled king if (isPiece(b, side, ChessPiece.Bishop, REL_SQ(side, ChessPosition.F1)) && isPiece(b, side, ChessPiece.King, REL_SQ(side, ChessPosition.G1))) { v.positionalThemes[side] += EvaluationData.RETURNING_BISHOP; } if (isPiece(b, side, ChessPiece.Bishop, REL_SQ(side, ChessPosition.C1)) && isPiece(b, side, ChessPiece.King, REL_SQ(side, ChessPosition.B1))) { v.positionalThemes[side] += EvaluationData.RETURNING_BISHOP; } // uncastled king blocking own rook if ((isPiece(b, side, ChessPiece.King, REL_SQ(side, ChessPosition.F1)) || isPiece(b, side, ChessPiece.King, REL_SQ(side, ChessPosition.G1))) && (isPiece(b, side, ChessPiece.Rook, REL_SQ(side, ChessPosition.H1)) || isPiece(b, side, ChessPiece.Rook, REL_SQ(side, ChessPosition.G1)))) { v.blockages[side] -= EvaluationData.P_KING_BLOCKS_ROOK; } if ((isPiece(b, side, ChessPiece.King, REL_SQ(side, ChessPosition.C1)) || isPiece(b, side, ChessPiece.King, REL_SQ(side, ChessPosition.B1))) && (isPiece(b, side, ChessPiece.Rook, REL_SQ(side, ChessPosition.A1)) || isPiece(b, side, ChessPiece.Rook, REL_SQ(side, ChessPosition.B1)))) { v.blockages[side] -= EvaluationData.P_KING_BLOCKS_ROOK; } }
private int EvaluateInner(Board board, Span <ulong> pins, EvaluationScores scores) { int result = 0; int mgScore = 0; int egScore = 0; int stronger = 0; int weaker = 0; var pawnControl = _pawnControl; pawnControl[ChessPiece.White] = _attacks.GetAttackedByPawns(board.BitBoard[ChessPiece.WhitePawn], true); pawnControl[ChessPiece.Black] = _attacks.GetAttackedByPawns(board.BitBoard[ChessPiece.BlackPawn], false); /************************************************************************** * Clear all eval data * **************************************************************************/ _evaluationScores.Clear(); scores.gamePhase = board.PieceCounts[ChessPiece.WhiteKnight] + board.PieceCounts[ChessPiece.WhiteBishop] + 2 * board.PieceCounts[ChessPiece.WhiteRook] + 4 * board.PieceCounts[ChessPiece.WhiteQueen] + board.PieceCounts[ChessPiece.BlackKnight] + board.PieceCounts[ChessPiece.BlackBishop] + 2 * board.PieceCounts[ChessPiece.BlackRook] + 4 * board.PieceCounts[ChessPiece.BlackQueen]; /************************************************************************** * add king's pawn shield score and evaluate part of piece blockage score * * (the rest of the latter will be done via piece eval) * **************************************************************************/ scores.kingShield[ChessPiece.White] = wKingShield(board); scores.kingShield[ChessPiece.Black] = bKingShield(board); blockedPieces(board, scores, ChessPiece.White); blockedPieces(board, scores, ChessPiece.Black); mgScore += (scores.kingShield[ChessPiece.White] - scores.kingShield[ChessPiece.Black]); /* tempo bonus */ if (board.WhiteToMove) { result += EvaluationData.TEMPO; } else { result -= EvaluationData.TEMPO; } /************************************************************************** * Adjusting material value for the various combinations of pieces. * * Currently it scores bishop, knight and rook pairs. The first one * * gets a bonus, the latter two - a penalty. Beside that knights lose * * value as pawns disappear, whereas rooks gain. * **************************************************************************/ if (board.PieceCounts[ChessPiece.WhiteBishop] > 1) { scores.adjustMaterial[ChessPiece.White] += EvaluationData.BISHOP_PAIR; } if (board.PieceCounts[ChessPiece.BlackBishop] > 1) { scores.adjustMaterial[ChessPiece.Black] += EvaluationData.BISHOP_PAIR; } if (board.PieceCounts[ChessPiece.WhiteKnight] > 1) { scores.adjustMaterial[ChessPiece.White] -= EvaluationData.P_KNIGHT_PAIR; } if (board.PieceCounts[ChessPiece.BlackKnight] > 1) { scores.adjustMaterial[ChessPiece.Black] -= EvaluationData.P_KNIGHT_PAIR; } if (board.PieceCounts[ChessPiece.WhiteRook] > 1) { scores.adjustMaterial[ChessPiece.White] -= EvaluationData.P_ROOK_PAIR; } if (board.PieceCounts[ChessPiece.BlackRook] > 1) { scores.adjustMaterial[ChessPiece.Black] -= EvaluationData.P_ROOK_PAIR; } scores.adjustMaterial[ChessPiece.White] += _evaluationData.n_adj[board.PieceCounts[ChessPiece.WhitePawn]] * board.PieceCounts[ChessPiece.WhiteKnight]; scores.adjustMaterial[ChessPiece.Black] += _evaluationData.n_adj[board.PieceCounts[ChessPiece.BlackPawn]] * board.PieceCounts[ChessPiece.BlackKnight]; scores.adjustMaterial[ChessPiece.White] += _evaluationData.r_adj[board.PieceCounts[ChessPiece.WhitePawn]] * board.PieceCounts[ChessPiece.WhiteRook]; scores.adjustMaterial[ChessPiece.Black] += _evaluationData.r_adj[board.PieceCounts[ChessPiece.BlackPawn]] * board.PieceCounts[ChessPiece.BlackRook]; var pawnScore = getPawnScore(board, pawnControl); result += pawnScore; /************************************************************************** * Evaluate pieces * **************************************************************************/ EvaluatePieces(board, scores, pawnControl, pins); /************************************************************************** * Sum the incrementally counted material and piece/square table values * **************************************************************************/ mgScore += board.PieceMaterial[ChessPiece.White] + board.PawnMaterial[ChessPiece.White] + scores.PieceSquaresMidgame[ChessPiece.White] - board.PieceMaterial[ChessPiece.Black] - board.PawnMaterial[ChessPiece.Black] - scores.PieceSquaresMidgame[ChessPiece.Black]; egScore += board.PieceMaterial[ChessPiece.White] + board.PawnMaterial[ChessPiece.White] + scores.PieceSquaresEndgame[ChessPiece.White] - board.PieceMaterial[ChessPiece.Black] - board.PawnMaterial[ChessPiece.Black] - scores.PieceSquaresEndgame[ChessPiece.Black]; /************************************************************************** * Merge midgame and endgame score. We interpolate between these two * * values, using a gamePhase value, based on remaining piece material on * * both sides. With less pieces, endgame score becomes more influential. * **************************************************************************/ mgScore += (scores.mgMob[ChessPiece.White] - scores.mgMob[ChessPiece.Black]); egScore += (scores.egMob[ChessPiece.White] - scores.egMob[ChessPiece.Black]); mgScore += (scores.mgTropism[ChessPiece.White] - scores.mgTropism[ChessPiece.Black]); egScore += (scores.egTropism[ChessPiece.White] - scores.egTropism[ChessPiece.Black]); if (scores.gamePhase > 24) { scores.gamePhase = 24; } int mgWeight = scores.gamePhase; int egWeight = 24 - mgWeight; result += ((mgScore * mgWeight) + (egScore * egWeight)) / 24; /************************************************************************** * Add phase-independent score components. * **************************************************************************/ result += (scores.blockages[ChessPiece.White] - scores.blockages[ChessPiece.Black]); result += (scores.positionalThemes[ChessPiece.White] - scores.positionalThemes[ChessPiece.Black]); result += (scores.adjustMaterial[ChessPiece.White] - scores.adjustMaterial[ChessPiece.Black]); /************************************************************************** * Merge king attack score. We don't apply this value if there are less * * than two attackers or if the attacker has no queen. * **************************************************************************/ if (scores.attCnt[ChessPiece.White] < 2 || board.PieceCounts[ChessPiece.WhiteQueen] == 0) { scores.attWeight[ChessPiece.White] = 0; } if (scores.attCnt[ChessPiece.Black] < 2 || board.PieceCounts[ChessPiece.BlackQueen] == 0) { scores.attWeight[ChessPiece.Black] = 0; } result += EvaluationData.SafetyTable[scores.attWeight[ChessPiece.White]]; result -= EvaluationData.SafetyTable[scores.attWeight[ChessPiece.Black]]; //result -= pins[ChessPiece.White].BitCount() * 5; //result += pins[ChessPiece.Black].BitCount() * 5; /************************************************************************** * Low material correction - guarding against an illusory material advan- * * tage. Full blown program should have more such rules, but the current * * set ought to be useful enough. Please note that our code assumes * * different material values for bishop and knight. * * * * - a single minor piece cannot win * * - two knights cannot checkmate bare king * * - bare rook vs minor piece is drawish * * - rook and minor vs rook is drawish * **************************************************************************/ if (result > 0) { stronger = ChessPiece.White; weaker = ChessPiece.Black; } else { stronger = ChessPiece.Black; weaker = ChessPiece.White; } if (board.PawnMaterial[stronger] == 0) { if (board.PieceMaterial[stronger] < 400) { return(0); } if (board.PawnMaterial[weaker] == 0 && (board.PieceMaterial[stronger] == 2 * EvaluationData.PIECE_VALUE[ChessPiece.Knight])) { return(0); } if ( board.PieceMaterial[stronger] == EvaluationData.PIECE_VALUE[ChessPiece.Rook] && board.PieceMaterial[weaker] == EvaluationData.PIECE_VALUE[ChessPiece.Knight] // TODO FIXED ) { result /= 2; } if ( board.PieceMaterial[stronger] == EvaluationData.PIECE_VALUE[ChessPiece.Rook] && board.PieceMaterial[weaker] == EvaluationData.PIECE_VALUE[ChessPiece.Bishop] ) { result /= 2; } if ( board.PieceMaterial[stronger] == EvaluationData.PIECE_VALUE[ChessPiece.Rook] + EvaluationData.PIECE_VALUE[ChessPiece.Knight] && board.PieceMaterial[weaker] == EvaluationData.PIECE_VALUE[ChessPiece.Rook] ) { result /= 2; } if ( board.PieceMaterial[stronger] == EvaluationData.PIECE_VALUE[ChessPiece.Rook] + EvaluationData.PIECE_VALUE[ChessPiece.Bishop] && board.PieceMaterial[weaker] == EvaluationData.PIECE_VALUE[ChessPiece.Rook] ) { result /= 2; } } /************************************************************************** * Finally return the score relative to the side to move. * **************************************************************************/ if (board.ColorToMove == ChessPiece.Black) { result = -result; } //tteval_save(result); return(result); }
void EvalQueen(Board b, EvaluationScores v, Position sq, Piece side, ulong pinned) { int att = 0; int mob = 0; //var sqCol = sq & 7; var sqRow = sq >> 3; var seventh = EvaluationData.seventh[side]; var eighth = EvaluationData.eighth[side]; if ( sqRow == seventh && ( (b.BitBoard[ChessPiece.Pawn + side ^ 1] & BitboardConstants.Ranks[seventh]) != 0 || (b.BitBoard[ChessPiece.King + side ^ 1] & BitboardConstants.Ranks[eighth]) != 0 ) ) { v.mgMob[side] += 5; v.egMob[side] += 10; } /************************************************************************** * A queen should not be developed too early * **************************************************************************/ if ((side == ChessPiece.White && sqRow > 1) || (side == ChessPiece.Black && sqRow < 6)) { if (isPiece(b, side, ChessPiece.Knight, REL_SQ(side, ChessPosition.B1))) { v.positionalThemes[side] -= 2; } if (isPiece(b, side, ChessPiece.Bishop, REL_SQ(side, ChessPosition.C1))) { v.positionalThemes[side] -= 2; } if (isPiece(b, side, ChessPiece.Bishop, REL_SQ(side, ChessPosition.F1))) { v.positionalThemes[side] -= 2; } if (isPiece(b, side, ChessPiece.Knight, REL_SQ(side, ChessPosition.G1))) { v.positionalThemes[side] -= 2; } } /************************************************************************** * Collect data about mobility and king attacks * **************************************************************************/ var slide = _slideGenerator.AllSlide(b.AllPieces, sq); var opponent = side == ChessPiece.White ? b.BlackPieces : b.WhitePieces; var emptyOrOpponent = (b.EmptySquares | opponent) & slide; var bitboard = 1UL << sq; if ((bitboard & pinned) == 0) { mob += emptyOrOpponent.PopCount(); } var emptyOrOpponentNearKing = emptyOrOpponent & BitboardConstants.KingExtendedJumps[side ^ 1][b.KingPositions[side ^ 1]]; att += emptyOrOpponentNearKing.PopCount(); v.mgMob[side] += 1 * (mob - 14); v.egMob[side] += 2 * (mob - 14); if (att > 0) { v.attCnt[side]++; v.attWeight[side] += 4 * att; } int tropism = getTropism(sq, b.KingPositions[side ^ 1]); v.mgTropism[side] += 2 * tropism; v.egTropism[side] += 4 * tropism; }
public void EvalRook(Board b, EvaluationScores v, Position sq, Piece side, ulong pinned) { int att = 0; int mob = 0; var sqCol = sq & 7; var sqRow = sq >> 3; /************************************************************************** * Bonus for rook on the seventh rank. It is applied when there are pawns * * to attack along that rank or if enemy king is cut off on 8th rank * * /*************************************************************************/ //if //( // sqRow == EvaluationData.seventh[side] // && (eb.pawns_on_rank[side ^ 1, EvaluationData.seventh[side]] > 0 || (b.KingPositions[side ^ 1]) == EvaluationData.eighth[side]) //) var seventh = EvaluationData.seventh[side]; var eighth = EvaluationData.eighth[side]; if ( sqRow == seventh && ( (b.BitBoard[ChessPiece.Pawn + side ^ 1] & BitboardConstants.Ranks[seventh]) != 0 || (b.BitBoard[ChessPiece.King + side ^ 1] & BitboardConstants.Ranks[eighth]) != 0 ) ) { v.mgMob[side] += 20; v.egMob[side] += 30; } /************************************************************************** * Bonus for open and half-open files is merged with mobility score. * * Bonus for open files targetting enemy king is added to attWeight[] * * /*************************************************************************/ var file = BitboardConstants.Files[sqCol]; var ownPawnsOnFile = b.BitBoard[ChessPiece.Pawn + side] & file; if (ownPawnsOnFile == 0) { var opponentPawnsOnFile = b.BitBoard[ChessPiece.Pawn + side ^ 1] & file; if (opponentPawnsOnFile == 0) // fully open file { v.mgMob[side] += EvaluationData.ROOK_OPEN; v.egMob[side] += EvaluationData.ROOK_OPEN; if (Math.Abs(sqCol - (b.KingPositions[side ^ 1] & 7)) < 2) { v.attWeight[side] += 1; } } else // half open file { v.mgMob[side] += EvaluationData.ROOK_HALF; v.egMob[side] += EvaluationData.ROOK_HALF; if (Math.Abs(sqCol - (b.KingPositions[side ^ 1] & 7)) < 2) { v.attWeight[side] += 2; } } } /************************************************************************** * Collect data about mobility and king attacks * **************************************************************************/ var slide = _slideGenerator.HorizontalVerticalSlide(b.AllPieces, sq); var opponent = side == ChessPiece.White ? b.BlackPieces : b.WhitePieces; var emptyOrOpponent = (b.EmptySquares | opponent) & slide; var bitboard = 1UL << sq; if ((bitboard & pinned) == 0) { mob += emptyOrOpponent.PopCount(); } var emptyOrOpponentNearKing = emptyOrOpponent & BitboardConstants.KingExtendedJumps[side ^ 1][b.KingPositions[side ^ 1]]; att += emptyOrOpponentNearKing.PopCount(); v.mgMob[side] += 2 * (mob - 7); v.egMob[side] += 4 * (mob - 7); if (att > 0) { v.attCnt[side]++; v.attWeight[side] += 3 * att; } int tropism = getTropism(sq, b.KingPositions[side ^ 1]); v.mgTropism[side] += 2 * tropism; v.egTropism[side] += 1 * tropism; }
void EvaluatePieces(Board b, EvaluationScores v, ulong[] pawnControl, Span <ulong> pins) { for (Piece color = 0; color <= 1; color++) { var pinned = pins[color]; var pawn = ChessPiece.Pawn + color; var pawns = b.BitBoard[pawn]; while (pawns != 0) { var pos = pawns.BitScanForward(); v.PieceSquaresMidgame[color] += _evaluationData.mgPst[pawn][pos]; v.PieceSquaresEndgame[color] += _evaluationData.egPst[pawn][pos]; pawns &= pawns - 1; } var knight = ChessPiece.Knight + color; var knights = b.BitBoard[knight]; while (knights != 0) { var pos = knights.BitScanForward(); EvalKnight(b, v, pos, color, pawnControl, pinned); v.PieceSquaresMidgame[color] += _evaluationData.mgPst[knight][pos]; v.PieceSquaresEndgame[color] += _evaluationData.egPst[knight][pos]; knights &= knights - 1; } var bishop = ChessPiece.Bishop + color; var bishops = b.BitBoard[bishop]; while (bishops != 0) { var pos = bishops.BitScanForward(); EvalBishop(b, v, pos, color, pawnControl, pinned); v.PieceSquaresMidgame[color] += _evaluationData.mgPst[bishop][pos]; v.PieceSquaresEndgame[color] += _evaluationData.egPst[bishop][pos]; bishops &= bishops - 1; } var rook = ChessPiece.Rook + color; var rooks = b.BitBoard[rook]; while (rooks != 0) { var pos = rooks.BitScanForward(); EvalRook(b, v, pos, color, pinned); v.PieceSquaresMidgame[color] += _evaluationData.mgPst[rook][pos]; v.PieceSquaresEndgame[color] += _evaluationData.egPst[rook][pos]; rooks &= rooks - 1; } var queen = ChessPiece.Queen + color; var queens = b.BitBoard[queen]; while (queens != 0) { var pos = queens.BitScanForward(); EvalQueen(b, v, pos, color, pinned); v.PieceSquaresMidgame[color] += _evaluationData.mgPst[queen][pos]; v.PieceSquaresEndgame[color] += _evaluationData.egPst[queen][pos]; queens &= queens - 1; } v.PieceSquaresMidgame[color] += _evaluationData.mgPst[ChessPiece.King + color][b.KingPositions[color]]; v.PieceSquaresEndgame[color] += _evaluationData.egPst[ChessPiece.King + color][b.KingPositions[color]]; } }