コード例 #1
0
 /// <summary>
 /// Generates available moves.
 /// </summary>
 /// <param name="opt">The generator parameters.</param>
 public static void Generate(GeneratorParameters opt)
 {
     CalculateMovesForSinglePush(opt);
     CalculateMovesForDoublePush(opt);
     CalculateDiagonalAttacks(7, 9, BitConstants.HFile, opt);
     CalculateDiagonalAttacks(9, 7, BitConstants.AFile, opt);
 }
コード例 #2
0
        /// <summary>
        /// Generates available moves.
        /// </summary>
        /// <param name="pieceType">The piece type.</param>
        /// <param name="opt">The generator parameters.</param>
        public static void Generate(PieceType pieceType, GeneratorParameters opt)
        {
            var piecesToParse = opt.Bitboard.Pieces[FastArray.GetPieceIndex(opt.FriendlyColor, pieceType)];

            while (piecesToParse != 0)
            {
                var pieceLSB = BitOperations.GetLSB(piecesToParse);
                piecesToParse = BitOperations.PopLSB(piecesToParse);

                var excludeFromAttacks = CalculateMoves(pieceType, pieceLSB, opt);
                CalculateAttacks(pieceLSB, excludeFromAttacks, opt);
            }
        }
コード例 #3
0
        /// <summary>
        /// Calculates X-Ray attacks when friendly pawn is on bishop way.
        /// </summary>
        /// <param name="pieceIndex">The field index with the specified bishop.</param>
        /// <param name="pattern">The bishop moves pattern.</param>
        /// <param name="opt">The generator parameters.</param>
        /// <returns>The attacks bitboard with pawn X-Ray attacks.</returns>
        private static ulong CalculatePawnBlockers(int pieceIndex, ulong pattern, GeneratorParameters opt)
        {
            var patternWithFriendlyBlockers = pattern;
            var allowedBlockers             = opt.Bitboard.Pieces[FastArray.GetPieceIndex(opt.FriendlyColor, PieceType.Pawn)];

            var piecePosition    = BitPositionConverter.ToPosition(pieceIndex);
            var friendlyBlockers = pattern & opt.FriendlyOccupancy & allowedBlockers;

            while (friendlyBlockers != 0)
            {
                var friendlyBlockerLSB = BitOperations.GetLSB(friendlyBlockers);
                friendlyBlockers = BitOperations.PopLSB(friendlyBlockers);

                var friendlyBlockerIndex    = BitOperations.GetBitIndex(friendlyBlockerLSB);
                var friendlyBlockerPosition = BitPositionConverter.ToPosition(friendlyBlockerIndex);

                switch (opt.FriendlyColor)
                {
                case Color.White when friendlyBlockerPosition.X > piecePosition.X && friendlyBlockerPosition.Y > piecePosition.Y && (friendlyBlockerLSB & (BitConstants.HFile | BitConstants.HRank)) == 0:
                {
                    patternWithFriendlyBlockers |= friendlyBlockerLSB << 7;
                    break;
                }

                case Color.White when friendlyBlockerPosition.X <piecePosition.X && friendlyBlockerPosition.Y> piecePosition.Y && (friendlyBlockerLSB & (BitConstants.AFile | BitConstants.HRank)) == 0:
                {
                    patternWithFriendlyBlockers |= friendlyBlockerLSB << 9;
                    break;
                }

                case Color.Black when friendlyBlockerPosition.X > piecePosition.X && friendlyBlockerPosition.Y < piecePosition.Y && (friendlyBlockerLSB & (BitConstants.HFile | BitConstants.ARank)) == 0:
                {
                    patternWithFriendlyBlockers |= friendlyBlockerLSB >> 9;
                    break;
                }

                case Color.Black when friendlyBlockerPosition.X < piecePosition.X && friendlyBlockerPosition.Y < piecePosition.Y && (friendlyBlockerLSB & (BitConstants.AFile | BitConstants.ARank)) == 0:
                {
                    patternWithFriendlyBlockers |= friendlyBlockerLSB >> 7;
                    break;
                }
                }
            }

            return(patternWithFriendlyBlockers);
        }
コード例 #4
0
        /// <summary>
        /// Calculates castling moves.
        /// </summary>
        /// <param name="opt">The generator parameters.</param>
        public static void CalculateCastling(GeneratorParameters opt)
        {
            var kingLSB        = CastlingConstants.InitialKingBitboard;
            var leftRookLSB    = CastlingConstants.InitialLeftRookBitboard;
            var rightRookLSB   = CastlingConstants.InitialRightRookBitboard;
            var shortMoveArea  = CastlingConstants.ShortCastlingMoveArea;
            var shortCheckArea = CastlingConstants.ShortCastlingCheckArea;
            var longMoveArea   = CastlingConstants.LongCastlingMoveArea;
            var longCheckArea  = CastlingConstants.LongCastlingCheckArea;
            var kingPosition   = InitialKingPosition;

            if (opt.FriendlyColor == Color.Black)
            {
                kingLSB        <<= 56;
                leftRookLSB    <<= 56;
                rightRookLSB   <<= 56;
                shortMoveArea  <<= 56;
                shortCheckArea <<= 56;
                longMoveArea   <<= 56;
                longCheckArea  <<= 56;

                kingPosition += new Position(0, 7);
            }

            if (IsCastlingPossible(CastlingType.Short, opt) &&
                IsKingOnPosition(kingLSB, opt) && IsRookOnPosition(rightRookLSB, opt) &&
                IsCastlingAreaEmpty(shortMoveArea, opt.OccupancySummary) &&
                !IsCastlingAreaChecked(opt.EnemyColor, shortCheckArea, opt))
            {
                var kingDestinationPosition = kingPosition + new Position(2, 0);
                var move = new CastlingMove(kingPosition, kingDestinationPosition, PieceType.King, opt.FriendlyColor, CastlingType.Short);

                opt.Bitboard.Moves.AddLast(move);
            }

            if (IsCastlingPossible(CastlingType.Long, opt) &&
                IsKingOnPosition(kingLSB, opt) && IsRookOnPosition(leftRookLSB, opt) &&
                IsCastlingAreaEmpty(longMoveArea, opt.OccupancySummary) &&
                !IsCastlingAreaChecked(opt.EnemyColor, longCheckArea, opt))
            {
                var kingDestinationPosition = kingPosition - new Position(2, 0);
                var move = new CastlingMove(kingPosition, kingDestinationPosition, PieceType.King, opt.FriendlyColor, CastlingType.Long);

                opt.Bitboard.Moves.AddLast(move);
            }
        }
コード例 #5
0
        /// <summary>
        /// Generates available moves.
        /// </summary>
        /// <param name="opt">The generator parameters.</param>
        public static void Generate(GeneratorParameters opt)
        {
            var piecesToParse = opt.Bitboard.Pieces[FastArray.GetPieceIndex(opt.FriendlyColor, PieceType.Knight)];

            while (piecesToParse != 0)
            {
                var pieceLSB = BitOperations.GetLSB(piecesToParse);
                piecesToParse = BitOperations.PopLSB(piecesToParse);

                var pieceIndex    = BitOperations.GetBitIndex(pieceLSB);
                var piecePosition = BitPositionConverter.ToPosition(pieceIndex);

                var pattern = PatternsContainer.KnightPattern[pieceIndex];

                while (pattern != 0)
                {
                    var patternLSB = BitOperations.GetLSB(pattern);
                    pattern = BitOperations.PopLSB(pattern);

                    var patternIndex = BitOperations.GetBitIndex(patternLSB);

                    if ((opt.Mode & GeneratorMode.CalculateMoves) != 0 && (patternLSB & opt.FriendlyOccupancy) == 0)
                    {
                        var to = BitPositionConverter.ToPosition(patternIndex);

                        if ((patternLSB & opt.EnemyOccupancy) == 0 && !opt.QuiescenceSearch)
                        {
                            opt.Bitboard.Moves.AddLast(new QuietMove(piecePosition, to, PieceType.Knight, opt.FriendlyColor));
                        }
                        else if ((patternLSB & opt.EnemyOccupancy) != 0)
                        {
                            opt.Bitboard.Moves.AddLast(new KillMove(piecePosition, to, PieceType.Knight, opt.FriendlyColor));
                        }
                    }

                    if ((opt.Mode & GeneratorMode.CalculateAttacks) != 0)
                    {
                        opt.Bitboard.Attacks[patternIndex] |= pieceLSB;
                        opt.Bitboard.AttacksSummary[(int)opt.FriendlyColor] |= patternLSB;
                    }
                }
            }
        }
コード例 #6
0
        /// <summary>
        /// Calculates double push moves.
        /// </summary>
        /// <param name="opt">The generator parameters.</param>
        private static void CalculateMovesForDoublePush(GeneratorParameters opt)
        {
            if ((opt.Mode & GeneratorMode.CalculateMoves) == 0 || opt.QuiescenceSearch)
            {
                return;
            }

            var   piecesToParse = opt.Bitboard.Pieces[FastArray.GetPieceIndex(opt.FriendlyColor, PieceType.Pawn)];
            ulong validPieces;
            ulong pattern;

            if (opt.FriendlyColor == Color.White)
            {
                validPieces  = piecesToParse & BitConstants.BRank;
                validPieces &= ~opt.OccupancySummary >> 8;
                pattern      = validPieces << 16;
            }
            else
            {
                validPieces  = piecesToParse & BitConstants.GRank;
                validPieces &= ~opt.OccupancySummary << 8;
                pattern      = validPieces >> 16;
            }

            pattern &= ~opt.OccupancySummary;

            while (pattern != 0)
            {
                var patternLSB = BitOperations.GetLSB(pattern);
                pattern = BitOperations.PopLSB(pattern);

                var patternIndex = BitOperations.GetBitIndex(patternLSB);

                var pieceLSB   = opt.FriendlyColor == Color.White ? patternLSB >> 16 : patternLSB << 16;
                var pieceIndex = BitOperations.GetBitIndex(pieceLSB);

                var from = BitPositionConverter.ToPosition(pieceIndex);
                var to   = BitPositionConverter.ToPosition(patternIndex);

                opt.Bitboard.Moves.AddLast(new QuietMove(from, to, PieceType.Pawn, opt.FriendlyColor));
            }
        }
コード例 #7
0
        /// <summary>
        /// Calculates single push moves.
        /// </summary>
        /// <param name="opt">The generator parameters.</param>
        private static void CalculateMovesForSinglePush(GeneratorParameters opt)
        {
            if ((opt.Mode & GeneratorMode.CalculateMoves) == 0)
            {
                return;
            }

            var piecesToParse = opt.Bitboard.Pieces[FastArray.GetPieceIndex(opt.FriendlyColor, PieceType.Pawn)];

            var promotionLine = GetPromotionLine(opt.FriendlyColor);

            var pattern = opt.FriendlyColor == Color.White ? piecesToParse << 8 : piecesToParse >> 8;

            pattern &= ~opt.OccupancySummary;

            while (pattern != 0)
            {
                var patternLSB = BitOperations.GetLSB(pattern);
                pattern = BitOperations.PopLSB(pattern);

                var patternIndex = BitOperations.GetBitIndex(patternLSB);

                var pieceLSB   = opt.FriendlyColor == Color.White ? patternLSB >> 8 : patternLSB << 8;
                var pieceIndex = BitOperations.GetBitIndex(pieceLSB);

                var from = BitPositionConverter.ToPosition(pieceIndex);
                var to   = BitPositionConverter.ToPosition(patternIndex);

                if ((patternLSB & promotionLine) == 0 && !opt.QuiescenceSearch)
                {
                    opt.Bitboard.Moves.AddLast(new QuietMove(from, to, PieceType.Pawn, opt.FriendlyColor));
                }
                else if ((patternLSB & promotionLine) != 0)
                {
                    opt.Bitboard.Moves.AddLast(new PromotionMove(from, to, PieceType.Pawn, opt.FriendlyColor, PieceType.Queen, false));
                    opt.Bitboard.Moves.AddLast(new PromotionMove(from, to, PieceType.Pawn, opt.FriendlyColor, PieceType.Rook, false));
                    opt.Bitboard.Moves.AddLast(new PromotionMove(from, to, PieceType.Pawn, opt.FriendlyColor, PieceType.Bishop, false));
                    opt.Bitboard.Moves.AddLast(new PromotionMove(from, to, PieceType.Pawn, opt.FriendlyColor, PieceType.Knight, false));
                }
            }
        }
コード例 #8
0
        /// <summary>
        /// Calculates attacks for the specified piece.
        /// </summary>
        /// <param name="pieceBitboard">The bitboard with set bit at piece position.</param>
        /// <param name="excludedFields">The bitboard with excluded fields from attacks calculating.</param>
        /// <param name="opt">The generator parameters.</param>
        private static void CalculateAttacks(ulong pieceBitboard, ulong excludedFields, GeneratorParameters opt)
        {
            if ((opt.Mode & GeneratorMode.CalculateAttacks) == 0)
            {
                return;
            }

            var pieceIndex       = BitOperations.GetBitIndex(pieceBitboard);
            var blockersToRemove = opt.Bitboard.Pieces[FastArray.GetPieceIndex(opt.FriendlyColor, PieceType.Bishop)] |
                                   opt.Bitboard.Pieces[FastArray.GetPieceIndex(opt.FriendlyColor, PieceType.Queen)];

            var allPiecesOccupancy = opt.OccupancySummary & ~blockersToRemove;

            var pattern = MagicContainer.GetBishopAttacks(pieceIndex, allPiecesOccupancy);

            pattern  = CalculatePawnBlockers(pieceIndex, pattern, opt);
            pattern ^= excludedFields;

            while (pattern != 0)
            {
                var patternLSB = BitOperations.GetLSB(pattern);
                pattern = BitOperations.PopLSB(pattern);

                var patternIndex = BitOperations.GetBitIndex(patternLSB);

                opt.Bitboard.Attacks[patternIndex] |= pieceBitboard;
                opt.Bitboard.AttacksSummary[(int)opt.FriendlyColor] |= patternLSB;
            }
        }
コード例 #9
0
        /// <summary>
        /// Calculates moves for the specified piece.
        /// </summary>
        /// <param name="pieceType">The piece type.</param>
        /// <param name="pieceBitboard">The bitboard with set bit at piece position.</param>
        /// <param name="opt">The generator parameters.</param>
        /// <returns>The bitboard with available moves for the specified piece.</returns>
        private static ulong CalculateMoves(PieceType pieceType, ulong pieceBitboard, GeneratorParameters opt)
        {
            if ((opt.Mode & GeneratorMode.CalculateMoves) == 0)
            {
                return(0);
            }

            var pieceIndex    = BitOperations.GetBitIndex(pieceBitboard);
            var piecePosition = BitPositionConverter.ToPosition(pieceIndex);

            var pattern = MagicContainer.GetBishopAttacks(pieceIndex, opt.OccupancySummary);

            pattern &= ~opt.FriendlyOccupancy;

            if (opt.QuiescenceSearch)
            {
                pattern &= opt.EnemyOccupancy;
            }

            var excludeFromAttacks = pattern;

            while (pattern != 0)
            {
                var patternLSB = BitOperations.GetLSB(pattern);
                pattern = BitOperations.PopLSB(pattern);

                var patternIndex = BitOperations.GetBitIndex(patternLSB);
                var to           = BitPositionConverter.ToPosition(patternIndex);

                if ((patternLSB & opt.EnemyOccupancy) == 0)
                {
                    opt.Bitboard.Moves.AddLast(new QuietMove(piecePosition, to, pieceType, opt.FriendlyColor));
                }
                else
                {
                    opt.Bitboard.Moves.AddLast(new KillMove(piecePosition, to, pieceType, opt.FriendlyColor));
                }

                if ((opt.Mode & GeneratorMode.CalculateAttacks) != 0)
                {
                    opt.Bitboard.Attacks[patternIndex] |= pieceBitboard;
                    opt.Bitboard.AttacksSummary[(int)opt.FriendlyColor] |= patternLSB;
                }
            }

            return(excludeFromAttacks);
        }
コード例 #10
0
 /// <summary>
 /// Checks if check area (all fields that are on the way of king during castling) is checked.
 /// </summary>
 /// <param name="enemyColor">The enemy color.</param>
 /// <param name="areaToCheck">The bitboard with set bit at all fields to check.</param>
 /// <param name="opt">The generator parameters.</param>
 /// <returns>True if any of the castling area is checked, otherwise false.</returns>
 private static bool IsCastlingAreaChecked(Color enemyColor, ulong areaToCheck, GeneratorParameters opt)
 {
     return((opt.Bitboard.AttacksSummary[(int)enemyColor] & areaToCheck) != 0);
 }
コード例 #11
0
 /// <summary>
 /// Checks if rook is on initial position and can be a part of castling.
 /// </summary>
 /// <param name="rookBitboard">The bitboard with set bit at rook position.</param>
 /// <param name="opt">The generator parameters.</param>
 /// <returns>True if rook is on initial position, otherwise false.</returns>
 private static bool IsRookOnPosition(ulong rookBitboard, GeneratorParameters opt)
 {
     return((opt.Bitboard.Pieces[FastArray.GetPieceIndex(opt.FriendlyColor, PieceType.Rook)] & rookBitboard) != 0);
 }
コード例 #12
0
 /// <summary>
 /// Checks if king is on initial position and can be a part of castling.
 /// </summary>
 /// <param name="kingBitboard">The bitboard with set bit at king position.</param>
 /// <param name="opt">The generator parameters.</param>
 /// <returns>True if king is on initial position, otherwise false.</returns>
 private static bool IsKingOnPosition(ulong kingBitboard, GeneratorParameters opt)
 {
     return((opt.Bitboard.Pieces[FastArray.GetPieceIndex(opt.FriendlyColor, PieceType.King)] & kingBitboard) != 0);
 }
コード例 #13
0
 /// <summary>
 /// Checks if castling with the specified type is possible.
 /// </summary>
 /// <param name="type">The castling type.</param>
 /// <param name="opt">The generator parameters.</param>
 /// <returns>True if castling is possible, otherwise false.</returns>
 private static bool IsCastlingPossible(CastlingType type, GeneratorParameters opt)
 {
     return(opt.Bitboard.CastlingPossibility[FastArray.GetCastlingIndex(opt.FriendlyColor, type)]);
 }
コード例 #14
0
        /// <summary>
        /// Calculates diagonal attacks (and moves if possible).
        /// </summary>
        /// <param name="leftAttackShift">The left attack shift.</param>
        /// <param name="rightAttackShift">The right attacks shift.</param>
        /// <param name="ignoreFields">The bitboard with fields to ignore (white and black pieces will have different ones).</param>
        /// <param name="opt">The generator parameters.</param>
        private static void CalculateDiagonalAttacks(int leftAttackShift, int rightAttackShift, ulong ignoreFields, GeneratorParameters opt)
        {
            var piecesToParse = opt.Bitboard.Pieces[FastArray.GetPieceIndex(opt.FriendlyColor, PieceType.Pawn)];
            var validPieces   = piecesToParse & ~ignoreFields;

            var pattern       = opt.FriendlyColor == Color.White ? validPieces << leftAttackShift : validPieces >> rightAttackShift;
            var promotionLine = GetPromotionLine(opt.FriendlyColor);

            while (pattern != 0)
            {
                var patternLSB = BitOperations.GetLSB(pattern);
                pattern = BitOperations.PopLSB(pattern);

                var patternIndex = BitOperations.GetBitIndex(patternLSB);

                var pieceLSB   = opt.FriendlyColor == Color.White ? patternLSB >> leftAttackShift : patternLSB << rightAttackShift;
                var pieceIndex = BitOperations.GetBitIndex(pieceLSB);

                if ((opt.Mode & GeneratorMode.CalculateMoves) != 0)
                {
                    var piecePosition  = BitPositionConverter.ToPosition(pieceIndex);
                    var enPassantField = opt.Bitboard.EnPassant[(int)opt.EnemyColor] & patternLSB;

                    if ((patternLSB & opt.EnemyOccupancy) != 0 || enPassantField != 0)
                    {
                        var to = BitPositionConverter.ToPosition(patternIndex);

                        if (enPassantField != 0)
                        {
                            opt.Bitboard.Moves.AddLast(new EnPassantMove(piecePosition, to, PieceType.Pawn, opt.FriendlyColor));
                        }
                        else if ((patternLSB & promotionLine) != 0)
                        {
                            opt.Bitboard.Moves.AddLast(new PromotionMove(piecePosition, to, PieceType.Pawn, opt.FriendlyColor, PieceType.Queen, true));
                            opt.Bitboard.Moves.AddLast(new PromotionMove(piecePosition, to, PieceType.Pawn, opt.FriendlyColor, PieceType.Rook, true));
                            opt.Bitboard.Moves.AddLast(new PromotionMove(piecePosition, to, PieceType.Pawn, opt.FriendlyColor, PieceType.Bishop, true));
                            opt.Bitboard.Moves.AddLast(new PromotionMove(piecePosition, to, PieceType.Pawn, opt.FriendlyColor, PieceType.Knight, true));
                        }
                        else
                        {
                            opt.Bitboard.Moves.AddLast(new KillMove(piecePosition, to, PieceType.Pawn, opt.FriendlyColor));
                        }
                    }
                }

                if ((opt.Mode & GeneratorMode.CalculateAttacks) != 0)
                {
                    opt.Bitboard.Attacks[patternIndex] |= pieceLSB;
                    opt.Bitboard.AttacksSummary[(int)opt.FriendlyColor] |= patternLSB;
                }
            }
        }