Пример #1
0
        public static int CalculateThreats(ChessBoard cb)
        {
            var score             = 0;
            var whites            = cb.Pieces[White][All];
            var whitePawns        = cb.Pieces[White][Pawn];
            var blacks            = cb.Pieces[Black][All];
            var blackPawns        = cb.Pieces[Black][Pawn];
            var whiteAttacks      = cb.Attacks[White][All];
            var whitePawnAttacks  = cb.Attacks[White][Pawn];
            var whiteMinorAttacks = cb.Attacks[White][Knight] | cb.Attacks[White][Bishop];
            var blackAttacks      = cb.Attacks[Black][All];
            var blackPawnAttacks  = cb.Attacks[Black][Pawn];
            var blackMinorAttacks = cb.Attacks[Black][Knight] | cb.Attacks[Black][Bishop];

            // double attacked pieces
            var piece = cb.DoubleAttacks[White] & blacks;

            while (piece != 0)
            {
                score += EvalConstants.DoubleAttacked[cb.PieceIndexes[BitOperations.TrailingZeroCount(piece)]];
                piece &= piece - 1;
            }

            piece = cb.DoubleAttacks[Black] & whites;
            while (piece != 0)
            {
                score -= EvalConstants.DoubleAttacked[cb.PieceIndexes[BitOperations.TrailingZeroCount(piece)]];
                piece &= piece - 1;
            }

            if (MaterialUtil.HasPawns(cb.MaterialKey))
            {
                // unused outposts
                score += BitOperations.PopCount((ulong)(cb.PassedPawnsAndOutposts & cb.EmptySpaces &
                                                        whiteMinorAttacks & whitePawnAttacks))
                         * EvalConstants.Threats[EvalConstants.IxUnusedOutpost];
                score -= BitOperations.PopCount((ulong)(cb.PassedPawnsAndOutposts & cb.EmptySpaces &
                                                        blackMinorAttacks & blackPawnAttacks))
                         * EvalConstants.Threats[EvalConstants.IxUnusedOutpost];

                // pawn push threat
                piece  = (whitePawns << 8) & cb.EmptySpaces & ~blackAttacks;
                score += BitOperations.PopCount((ulong)(Bitboard.GetWhitePawnAttacks(piece) & blacks)) *
                         EvalConstants.Threats[EvalConstants.IxPawnPushThreat];
                piece  = Util.RightTripleShift(blackPawns, 8) & cb.EmptySpaces & ~whiteAttacks;
                score -= BitOperations.PopCount((ulong)(Bitboard.GetBlackPawnAttacks(piece) & whites)) *
                         EvalConstants.Threats[EvalConstants.IxPawnPushThreat];

                // piece attacked by pawn
                score += BitOperations.PopCount((ulong)(whitePawnAttacks & blacks & ~blackPawns)) *
                         EvalConstants.Threats[EvalConstants.IxPawnAttacks];
                score -= BitOperations.PopCount((ulong)(blackPawnAttacks & whites & ~whitePawns)) *
                         EvalConstants.Threats[EvalConstants.IxPawnAttacks];

                // multiple pawn attacks possible
                if (BitOperations.PopCount((ulong)(whitePawnAttacks & blacks)) > 1)
                {
                    score += EvalConstants.Threats[EvalConstants.IxMultiplePawnAttacks];
                }

                if (BitOperations.PopCount((ulong)(blackPawnAttacks & whites)) > 1)
                {
                    score -= EvalConstants.Threats[EvalConstants.IxMultiplePawnAttacks];
                }

                // pawn attacked
                score += BitOperations.PopCount((ulong)(whiteAttacks & blackPawns)) *
                         EvalConstants.Threats[EvalConstants.IxPawnAttacked];
                score -= BitOperations.PopCount((ulong)(blackAttacks & whitePawns)) *
                         EvalConstants.Threats[EvalConstants.IxPawnAttacked];
            }

            // minors attacked and not defended by a pawn
            score += BitOperations.PopCount((ulong)(whiteAttacks &
                                                    (cb.Pieces[Black][Knight] |
                                                     (cb.Pieces[Black][Bishop] & ~blackAttacks))))
                     * EvalConstants.Threats[EvalConstants.IxMajorAttacked];
            score -= BitOperations.PopCount((ulong)(blackAttacks &
                                                    (cb.Pieces[White][Knight] |
                                                     (cb.Pieces[White][Bishop] & ~whiteAttacks))))
                     * EvalConstants.Threats[EvalConstants.IxMajorAttacked];

            if (cb.Pieces[Black][Queen] != 0)
            {
                // queen attacked by rook
                score += BitOperations.PopCount((ulong)(cb.Attacks[White][Rook] & cb.Pieces[Black][Queen])) *
                         EvalConstants.Threats[EvalConstants.IxQueenAttacked];
                // queen attacked by minors
                score += BitOperations.PopCount((ulong)(whiteMinorAttacks & cb.Pieces[Black][Queen])) *
                         EvalConstants.Threats[EvalConstants.IxQueenAttackedMinor];
            }

            if (cb.Pieces[White][Queen] != 0)
            {
                // queen attacked by rook
                score -= BitOperations.PopCount((ulong)(cb.Attacks[Black][Rook] & cb.Pieces[White][Queen])) *
                         EvalConstants.Threats[EvalConstants.IxQueenAttacked];
                // queen attacked by minors
                score -= BitOperations.PopCount((ulong)(blackMinorAttacks & cb.Pieces[White][Queen])) *
                         EvalConstants.Threats[EvalConstants.IxQueenAttackedMinor];
            }

            // rook attacked by minors
            score += BitOperations.PopCount((ulong)(whiteMinorAttacks & cb.Pieces[Black][Rook])) *
                     EvalConstants.Threats[EvalConstants.IxRookAttacked];
            score -= BitOperations.PopCount((ulong)(blackMinorAttacks & cb.Pieces[White][Rook])) *
                     EvalConstants.Threats[EvalConstants.IxRookAttacked];

            return(score);
        }
Пример #2
0
        private static int CalculatePawnScores(ChessBoard cb)
        {
            var score = 0;

            // penalty for doubled pawns
            for (var i = 0; i < 8; i++)
            {
                if (BitOperations.PopCount((ulong)(cb.Pieces[White][Pawn] & Bitboard.Files[i])) > 1)
                {
                    score -= EvalConstants.PawnScores[EvalConstants.IxPawnDouble];
                }

                if (BitOperations.PopCount((ulong)(cb.Pieces[Black][Pawn] & Bitboard.Files[i])) > 1)
                {
                    score += EvalConstants.PawnScores[EvalConstants.IxPawnDouble];
                }
            }

            // bonus for connected pawns
            var pawns = Bitboard.GetWhitePawnAttacks(cb.Pieces[White][Pawn]) & cb.Pieces[White][Pawn];

            while (pawns != 0)
            {
                score += EvalConstants.PawnConnected[BitOperations.TrailingZeroCount(pawns) / 8];
                pawns &= pawns - 1;
            }

            pawns = Bitboard.GetBlackPawnAttacks(cb.Pieces[Black][Pawn]) & cb.Pieces[Black][Pawn];
            while (pawns != 0)
            {
                score -= EvalConstants.PawnConnected[7 - BitOperations.TrailingZeroCount(pawns) / 8];
                pawns &= pawns - 1;
            }

            // bonus for neighbour pawns
            pawns = Bitboard.GetPawnNeighbours(cb.Pieces[White][Pawn]) & cb.Pieces[White][Pawn];
            while (pawns != 0)
            {
                score += EvalConstants.PawnNeighbour[BitOperations.TrailingZeroCount(pawns) / 8];
                pawns &= pawns - 1;
            }

            pawns = Bitboard.GetPawnNeighbours(cb.Pieces[Black][Pawn]) & cb.Pieces[Black][Pawn];
            while (pawns != 0)
            {
                score -= EvalConstants.PawnNeighbour[7 - BitOperations.TrailingZeroCount(pawns) / 8];
                pawns &= pawns - 1;
            }

            // set outposts
            cb.PassedPawnsAndOutposts = 0;
            pawns = Bitboard.GetWhitePawnAttacks(cb.Pieces[White][Pawn]) & ~cb.Pieces[White][Pawn] &
                    ~cb.Pieces[Black][Pawn];
            while (pawns != 0)
            {
                if ((Bitboard.GetWhiteAdjacentMask(BitOperations.TrailingZeroCount(pawns)) & cb.Pieces[Black][Pawn]) ==
                    0)
                {
                    cb.PassedPawnsAndOutposts |= pawns & -pawns;
                }

                pawns &= pawns - 1;
            }

            pawns = Bitboard.GetBlackPawnAttacks(cb.Pieces[Black][Pawn]) & ~cb.Pieces[White][Pawn] &
                    ~cb.Pieces[Black][Pawn];
            while (pawns != 0)
            {
                if ((Bitboard.GetBlackAdjacentMask(BitOperations.TrailingZeroCount(pawns)) & cb.Pieces[White][Pawn]) ==
                    0)
                {
                    cb.PassedPawnsAndOutposts |= pawns & -pawns;
                }

                pawns &= pawns - 1;
            }

            int index;

            // white
            pawns = cb.Pieces[White][Pawn];
            while (pawns != 0)
            {
                index = BitOperations.TrailingZeroCount(pawns);

                // isolated pawns
                if ((Bitboard.FilesAdjacent[index & 7] & cb.Pieces[White][Pawn]) == 0)
                {
                    score -= EvalConstants.PawnScores[EvalConstants.IxPawnIsolated];
                }

                // backward pawns
                else if ((Bitboard.GetBlackAdjacentMask(index + 8) & cb.Pieces[White][Pawn]) == 0)
                {
                    if ((StaticMoves.PawnAttacks[White][index + 8] & cb.Pieces[Black][Pawn]) != 0)
                    {
                        if ((Bitboard.Files[index & 7] & cb.Pieces[Black][Pawn]) == 0)
                        {
                            score -= EvalConstants.PawnScores[EvalConstants.IxPawnBackward];
                        }
                    }
                }

                // pawn defending 2 pawns
                if (BitOperations.PopCount((ulong)(StaticMoves.PawnAttacks[White][index] & cb.Pieces[White][Pawn])) ==
                    2)
                {
                    score -= EvalConstants.PawnScores[EvalConstants.IxPawnInverse];
                }

                // set passed pawns
                if ((Bitboard.GetWhitePassedPawnMask(index) & cb.Pieces[Black][Pawn]) == 0)
                {
                    cb.PassedPawnsAndOutposts |= pawns & -pawns;
                }

                // candidate passed pawns (no pawns in front, more friendly pawns behind and adjacent than enemy pawns)
                else if (63 - BitOperations.LeadingZeroCount(
                             (ulong)((cb.Pieces[White][Pawn] | cb.Pieces[Black][Pawn]) &
                                     Bitboard.Files[index & 7])) == index)
                {
                    if (BitOperations.PopCount((ulong)(cb.Pieces[White][Pawn] &
                                                       Bitboard.GetBlackPassedPawnMask(index + 8))) >=
                        BitOperations.PopCount(
                            (ulong)(cb.Pieces[Black][Pawn] & Bitboard.GetWhitePassedPawnMask(index))))
                    {
                        score += EvalConstants.PassedCandidate[index / 8];
                    }
                }

                pawns &= pawns - 1;
            }

            // black
            pawns = cb.Pieces[Black][Pawn];
            while (pawns != 0)
            {
                index = BitOperations.TrailingZeroCount(pawns);

                // isolated pawns
                if ((Bitboard.FilesAdjacent[index & 7] & cb.Pieces[Black][Pawn]) == 0)
                {
                    score += EvalConstants.PawnScores[EvalConstants.IxPawnIsolated];
                }

                // backward pawns
                else if ((Bitboard.GetWhiteAdjacentMask(index - 8) & cb.Pieces[Black][Pawn]) == 0)
                {
                    if ((StaticMoves.PawnAttacks[Black][index - 8] & cb.Pieces[White][Pawn]) != 0)
                    {
                        if ((Bitboard.Files[index & 7] & cb.Pieces[White][Pawn]) == 0)
                        {
                            score += EvalConstants.PawnScores[EvalConstants.IxPawnBackward];
                        }
                    }
                }

                // pawn defending 2 pawns
                if (BitOperations.PopCount((ulong)(StaticMoves.PawnAttacks[Black][index] & cb.Pieces[Black][Pawn])) ==
                    2)
                {
                    score += EvalConstants.PawnScores[EvalConstants.IxPawnInverse];
                }

                // set passed pawns
                if ((Bitboard.GetBlackPassedPawnMask(index) & cb.Pieces[White][Pawn]) == 0)
                {
                    cb.PassedPawnsAndOutposts |= pawns & -pawns;
                }

                // candidate passers
                else if (BitOperations.TrailingZeroCount((cb.Pieces[White][Pawn] | cb.Pieces[Black][Pawn]) &
                                                         Bitboard.Files[index & 7]) == index)
                {
                    if (BitOperations.PopCount((ulong)(cb.Pieces[Black][Pawn] &
                                                       Bitboard.GetWhitePassedPawnMask(index - 8))) >=
                        BitOperations.PopCount(
                            (ulong)(cb.Pieces[White][Pawn] & Bitboard.GetBlackPassedPawnMask(index))))
                    {
                        score -= EvalConstants.PassedCandidate[7 - index / 8];
                    }
                }

                pawns &= pawns - 1;
            }

            return(score);
        }