Exemplo n.º 1
0
    internal static ExtMoveArrayWrapper generate_castling(
        CastlingRight Cr,
        bool Checks,
        bool Chess960,
        Position pos,
        ExtMoveArrayWrapper moveList,
        ColorT us,
        CheckInfo ci)
    {
        var KingSide = (Cr == CastlingRight.WHITE_OO || Cr == CastlingRight.BLACK_OO);

        if (pos.castling_impeded(Cr) || !pos.can_castle(Cr))
        {
            return moveList;
        }

        // After castling, the rook and king final positions are the same in Chess960
        // as they would be in standard chess.
        var kfrom = pos.square(PieceType.KING, us);
        var rfrom = pos.castling_rook_square(Cr);
        var kto = Square.relative_square(us, KingSide ? Square.SQ_G1 : Square.SQ_C1);
        var enemies = pos.pieces_Ct(Color.opposite(us));

        Debug.Assert(pos.checkers() == 0);

        var K = Chess960 ? kto > kfrom ? Square.DELTA_W : Square.DELTA_E : KingSide ? Square.DELTA_W : Square.DELTA_E;

        for (var s = kto; s != kfrom; s += K)
        {
            if ((pos.attackers_to(s) & enemies) != 0)
            {
                return moveList;
            }
        }

        // Because we generate only legal castling moves we need to verify that
        // when moving the castling rook we do not discover some hidden checker.
        // For instance an enemy queen in SQ_A1 when castling rook is in SQ_B1.
        if (Chess960
            && ((Utils.attacks_bb_PtSBb(PieceType.ROOK, kto, Bitboard.XorWithSquare(pos.pieces(), rfrom))
                & pos.pieces_CtPtPt(Color.opposite(us), PieceType.ROOK, PieceType.QUEEN)))!= 0)
        {
            return moveList;
        }

        var m = Move.make(MoveType.CASTLING, kfrom, rfrom);

        if (Checks && !pos.gives_check(m, ci))
        {
            return moveList;
        }

        moveList.Add(m);
        return moveList;
    }
Exemplo n.º 2
0
    // evaluate_pieces() assigns bonuses and penalties to the pieces of a given color

    private static ScoreT evaluate_pieces(
        PieceTypeT pieceType,
        ColorT Us,
        bool DoTrace,
        Position pos,
        EvalInfo ei,
        ScoreT[] mobility,
        BitboardT[] mobilityArea)
    {
        int Pt = pieceType;
        if (Pt == PieceType.KING)
        {
            return Score.SCORE_ZERO;
        }
        var score = Score.SCORE_ZERO;

        var NextPt = (Us == Color.WHITE ? pieceType : pieceType + 1);
        var Them = (Us == Color.WHITE ? Color.BLACK : Color.WHITE);
        
        ei.attackedBy[Us, Pt] = Bitboard.Create(0);

        for(var idx=0; idx<16;idx++)
        {
            var s = pos.square(pieceType, Us, idx);
            if (s == Square.SQ_NONE)
            {
                break;
            }
            // Find attacked squares, including x-ray attacks for bishops and rooks
            var b = Pt == PieceType.BISHOP
                ? Utils.attacks_bb_PtSBb(PieceType.BISHOP, s, pos.pieces() ^ pos.pieces_CtPt(Us, PieceType.QUEEN))
                : Pt == PieceType.ROOK
                    ? Utils.attacks_bb_PtSBb(
                        PieceType.ROOK,
                        s,
                        pos.pieces() ^ pos.pieces_CtPtPt(Us, PieceType.ROOK, PieceType.QUEEN))
                    : pos.attacks_from_PtS(pieceType, s);

            if (Bitboard.AndWithSquare(ei.pinnedPieces[Us], s)!=0)
            {
                b &= Utils.LineBB[pos.square(PieceType.KING, Us), s];
            }

            ei.attackedBy[Us, PieceType.ALL_PIECES] |= ei.attackedBy[Us, Pt] |= b;

            if ((b & ei.kingRing[Them])!=0)
            {
                ei.kingAttackersCount[Us]++;
                ei.kingAttackersWeight[Us] += KingAttackWeights[Pt];
                var bb = b & ei.attackedBy[Them, PieceType.KING];
                if (bb!=0)
                {
                    ei.kingAdjacentZoneAttacksCount[Us] += Bitcount.popcount_Max15(bb);
                }
            }

            if (Pt == PieceType.QUEEN)
            {
                b &=
                    ~(ei.attackedBy[Them, PieceType.KNIGHT] | ei.attackedBy[Them, PieceType.BISHOP]
                      | ei.attackedBy[Them, PieceType.ROOK]);
            }

            var mob = Pt == PieceType.QUEEN
                ? Bitcount.popcount_Full(b & mobilityArea[Us])
                : Bitcount.popcount_Max15(b & mobilityArea[Us]);

            mobility[Us] += MobilityBonus[Pt][mob];

            if (Pt == PieceType.BISHOP || Pt == PieceType.KNIGHT)
            {
                // Bonus for outpost square
                if (Rank.relative_rank_CtSt(Us, s) >= Rank.RANK_4 && Rank.relative_rank_CtSt(Us, s) <= Rank.RANK_6
                    && (pos.pieces_CtPt(Them, PieceType.PAWN) & Utils.pawn_attack_span(Us, s))==0)
                {
                    score +=
                        Outpost[Pt == PieceType.BISHOP ? 1 : 0][Bitboard.AndWithSquare(ei.attackedBy[Us, PieceType.PAWN], s)!=0 ? 1 : 0];
                }

                // Bonus when behind a pawn
                if (Rank.relative_rank_CtSt(Us, s) < Rank.RANK_5 && Bitboard.AndWithSquare(pos.pieces_Pt(PieceType.PAWN), (s + Square.pawn_push(Us)))!=0)
                {
                    score += MinorBehindPawn;
                }

                // Penalty for pawns on same color square of bishop
                if (Pt == PieceType.BISHOP)
                {
                    score -= BishopPawns*ei.pi.pawns_on_same_color_squares(Us, s);
                }

                // An important Chess960 pattern: A cornered bishop blocked by a friendly
                // pawn diagonally in front of it is a very serious problem, especially
                // when that pawn is also blocked.
                if (Pt == PieceType.BISHOP && pos.is_chess960()
                    && (s == Square.relative_square(Us, Square.SQ_A1) || s == Square.relative_square(Us, Square.SQ_H1)))
                {
                    var d = Square.pawn_push(Us) + (Square.file_of(s) == File.FILE_A ? Square.DELTA_E : Square.DELTA_W);
                    if (pos.piece_on(s + d) == Piece.make_piece(Us, PieceType.PAWN))
                    {
                        score -= !pos.empty(s + d + Square.pawn_push(Us))
                            ? TrappedBishopA1H1*4
                            : pos.piece_on(s + d + d) == Piece.make_piece(Us, PieceType.PAWN)
                                ? TrappedBishopA1H1*2
                                : TrappedBishopA1H1;
                    }
                }
            }

            if (Pt == PieceType.ROOK)
            {
                // Bonus for aligning with enemy pawns on the same rank/file
                if (Rank.relative_rank_CtSt(Us, s) >= Rank.RANK_5)
                {
                    var alignedPawns = pos.pieces_CtPt(Them, PieceType.PAWN) & Utils.PseudoAttacks[PieceType.ROOK, s];
                    if (alignedPawns!=0)
                    {
                        score += Bitcount.popcount_Max15(alignedPawns)*RookOnPawn;
                    }
                }

                // Bonus when on an open or semi-open file
                if (ei.pi.semiopen_file(Us, Square.file_of(s)) != 0)
                {
                    score += ei.pi.semiopen_file(Them, Square.file_of(s)) != 0 ? RookOnOpenFile : RookOnSemiOpenFile;
                }

                // Penalize when trapped by the king, even more if king cannot castle
                if (mob <= 3 && 0 == ei.pi.semiopen_file(Us, Square.file_of(s)))
                {
                    var ksq = pos.square(PieceType.KING, Us);

                    if (((Square.file_of(ksq) < File.FILE_E) == (Square.file_of(s) < Square.file_of(ksq)))
                        && (Square.rank_of(ksq) == Square.rank_of(s) || Rank.relative_rank_CtSt(Us, ksq) == Rank.RANK_1)
                        && 0 == ei.pi.semiopen_side(Us, Square.file_of(ksq), Square.file_of(s) < Square.file_of(ksq)))
                    {
                        score -= (TrappedRook - Score.make_score(mob*22, 0))*(1 + (pos.can_castle(Us) == 0 ? 1 : 0));
                    }
                }
            }
        }

        if (DoTrace)
        {
            add_IdxCtSt(Pt, Us, score);
        }
        // Recursively call evaluate_pieces() of next piece type until KING excluded
        return score - evaluate_pieces(NextPt, Them, DoTrace, pos, ei, mobility, mobilityArea);
    }