/// generate /// EVASIONS /// generates all pseudo-legal check evasions when the side /// to move is in check. Returns a pointer to the end of the move list. private static ExtMoveArrayWrapper generate_EVASIONS(Position pos, ExtMoveArrayWrapper moveList) { Debug.Assert(pos.checkers() != 0); var us = pos.side_to_move(); var ksq = pos.square(PieceType.KING, us); var sliderAttacks = Bitboard.Create(0); var sliders = pos.checkers() & ~pos.pieces_PtPt(PieceType.KNIGHT, PieceType.PAWN); // Find all the squares attacked by slider checkers. We will remove them from // the king evasions in order to skip known illegal moves, which avoids any // useless legality checks later on. while (sliders != 0) { var checksq1 = Utils.pop_lsb(ref sliders); sliderAttacks |= Bitboard.XorWithSquare(Utils.LineBB[checksq1, ksq], checksq1); } // Generate evasions for king, capture and non capture moves var b = pos.attacks_from_PtS(PieceType.KING, ksq) & ~pos.pieces_Ct(us) & ~sliderAttacks; while (b != 0) { (moveList).Add(Move.make_move(ksq, Utils.pop_lsb(ref b))); } if (Bitboard.more_than_one(pos.checkers())) { return moveList; // Double check, only a king move can save the day } // Generate blocking evasions or captures of the checking piece var checksq = Utils.lsb(pos.checkers()); var target = Bitboard.OrWithSquare(Utils.between_bb(checksq, ksq), checksq); return us == Color.WHITE ? generate_all(Color.WHITE, GenType.EVASIONS, pos, moveList, target) : generate_all(Color.BLACK, GenType.EVASIONS, pos, moveList, target); }
// evaluate_passed_pawns() evaluates the passed pawns of the given color private static ScoreT evaluate_passed_pawns(ColorT Us, bool DoTrace, Position pos, EvalInfo ei) { var Them = (Us == Color.WHITE ? Color.BLACK : Color.WHITE); var score = Score.SCORE_ZERO; var b = ei.pi.passed_pawns(Us); while (b!=0) { var s = Utils.pop_lsb(ref b); Debug.Assert(pos.pawn_passed(Us, s)); int r = Rank.relative_rank_CtSt(Us, s) - Rank.RANK_2; var rr = r*(r - 1); ValueT mbonus = Passed[(int) Phase.MG][r], ebonus = Passed[(int) Phase.EG][r]; if (rr != 0) { var blockSq = s + Square.pawn_push(Us); // Adjust bonus based on the king's proximity ebonus += Utils.distance_Square(pos.square(PieceType.KING, Them), blockSq)*5*rr - Utils.distance_Square(pos.square(PieceType.KING, Us), blockSq)*2*rr; // If blockSq is not the queening square then consider also a second push if (Rank.relative_rank_CtSt(Us, blockSq) != Rank.RANK_8) { ebonus -= Utils.distance_Square(pos.square(PieceType.KING, Us), blockSq + Square.pawn_push(Us))*rr; } // If the pawn is free to advance, then increase the bonus if (pos.empty(blockSq)) { // If there is a rook or queen attacking/defending the pawn from behind, // consider all the squaresToQueen. Otherwise consider only the squares // in the pawn's path attacked or occupied by the enemy. BitboardT squaresToQueen; BitboardT unsafeSquares; var defendedSquares = unsafeSquares = squaresToQueen = Utils.forward_bb(Us, s); var bb = Utils.forward_bb(Them, s) & pos.pieces_PtPt(PieceType.ROOK, PieceType.QUEEN) & pos.attacks_from_PtS(PieceType.ROOK, s); if ((pos.pieces_Ct(Us) & bb)==0) { defendedSquares &= ei.attackedBy[Us, PieceType.ALL_PIECES]; } if ((pos.pieces_Ct(Them) & bb) == 0) { unsafeSquares &= ei.attackedBy[Them, PieceType.ALL_PIECES] | pos.pieces_Ct(Them); } // If there aren't any enemy attacks, assign a big bonus. Otherwise // assign a smaller bonus if the block square isn't attacked. var k = unsafeSquares == 0 ? 18 : Bitboard.AndWithSquare(unsafeSquares, blockSq)==0 ? 8 : 0; // If the path to queen is fully defended, assign a big bonus. // Otherwise assign a smaller bonus if the block square is defended. if (defendedSquares == squaresToQueen) { k += 6; } else if (Bitboard.AndWithSquare(defendedSquares, blockSq)!=0) { k += 4; } mbonus += k*rr; ebonus += k*rr; } else if (Bitboard.AndWithSquare(pos.pieces_Ct(Us), blockSq)!=0) { mbonus += rr*3 + r*2 + 3; ebonus += rr + r*2; } } // rr != 0 if (pos.count(PieceType.PAWN, Us) < pos.count(PieceType.PAWN, Them)) { ebonus += ebonus/4; } score += Score.make_score(mbonus, ebonus) + PassedFile[Square.file_of(s)]; } if (DoTrace) { add_IdxCtSt((int) Term.PASSED, Us, Score.Multiply(score, Weights[PassedPawns])); } // Add the scores to the middlegame and endgame eval return Score.Multiply(score, Weights[PassedPawns]); }