/// <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;
            }
        }
        /// <summary>
        /// Checks if there is a G4/G5 sacrifice pattern (enemy sacrifice light piece to open file near to the king and
        /// attack him with the Queen/Rook).
        /// </summary>
        /// <param name="bitboard">The bitboard.</param>
        /// <param name="move">The move.</param>
        /// <returns>True if patterns is detected and move should be pruned, otherwise false.</returns>
        private bool IsG4G5Sacrifice(Bitboard bitboard, Move move)
        {
            const ulong whiteTrapField = 0x0000000200000000;
            const ulong blackTrapField = 0x0000000002000000;

            var castlingDone       = bitboard.CastlingDone[(int)move.Color];
            var regularGamePhase   = bitboard.GamePhase == GamePhase.Regular;
            var moveDetected       = false;
            var lightPieceDetected = false;

            var whitePiecesTrap = bitboard.Pieces[FastArray.GetPieceIndex(Color.White, PieceType.Knight)] |
                                  bitboard.Pieces[FastArray.GetPieceIndex(Color.White, PieceType.Bishop)];

            var blackPiecesTrap = bitboard.Pieces[FastArray.GetPieceIndex(Color.Black, PieceType.Knight)] |
                                  bitboard.Pieces[FastArray.GetPieceIndex(Color.Black, PieceType.Bishop)];

            switch (move.Color)
            {
            case Color.White:
            {
                moveDetected       = move.From == new Position(8, 3) && move.To == new Position(7, 4);
                lightPieceDetected = (blackPiecesTrap & blackTrapField) != 0;
                break;
            }

            case Color.Black:
            {
                moveDetected       = move.From == new Position(8, 6) && move.To == new Position(7, 5);
                lightPieceDetected = (whitePiecesTrap & whiteTrapField) != 0;
                break;
            }
            }

            return(castlingDone && regularGamePhase && moveDetected && lightPieceDetected);
        }
Beispiel #3
0
        /// <summary>
        /// Removes en passant piece from the specified bitboard.
        /// </summary>
        /// <param name="bitboard">The bitboard.</param>
        /// <param name="enemyColor">The enemy color.</param>
        /// <param name="fieldLSB">The bitboard with set field.</param>
        private void RemoveEnPassantPiece(Bitboard bitboard, Color enemyColor, ulong fieldLSB)
        {
            var enPassantPiece = Color == Color.White ? fieldLSB >> 8 : fieldLSB << 8;

            bitboard.Pieces[FastArray.GetPieceIndex(enemyColor, PieceType.Pawn)] &= ~enPassantPiece;
            bitboard.Occupancy[(int)enemyColor] ^= enPassantPiece;

            IncrementalMaterial.RemovePiece(bitboard, enemyColor, PieceType.Pawn);
            IncrementalPosition.RemovePiece(bitboard, enemyColor, PieceType.Pawn, enPassantPiece);
            IncrementalZobrist.AddOrRemovePiece(enemyColor, PieceType.Pawn, enPassantPiece, bitboard);
        }
        /// <summary>
        /// Checks if king with the specified color is checked.
        /// </summary>
        /// <param name="color">The king color.</param>
        /// <returns>True if king with specified color is checked, otherwise false.</returns>
        public bool IsCheck(Color color)
        {
            if (!_calculated)
            {
                throw new BitboardNotCalculatedException();
            }

            var enemyColor = ColorOperations.Invert(color);
            var king       = Pieces[FastArray.GetPieceIndex(color, PieceType.King)];

            return((AttacksSummary[(int)enemyColor] & king) != 0);
        }
        /// <summary>
        /// Gets a pieces array (for bitboards).
        /// </summary>
        /// <returns>The pieces array.</returns>
        public ulong[] GetPiecesArray()
        {
            var pieces = new ulong[12];

            foreach (var piece in Pieces)
            {
                var bitPosition = BitPositionConverter.ToULong(piece.Position);
                pieces[FastArray.GetPieceIndex(piece.Color, piece.Type)] |= bitPosition;
            }

            return(pieces);
        }
        /// <summary>
        /// Calculates occupancy for all players.
        /// </summary>
        /// <returns>The occupancy array.</returns>
        private ulong[] CalculateOccupancy()
        {
            var occupancy = new ulong[2];

            for (var piece = 0; piece < 6; piece++)
            {
                occupancy[(int)Color.White] |= Pieces[FastArray.GetPieceIndex(Color.White, (PieceType)piece)];
                occupancy[(int)Color.Black] |= Pieces[FastArray.GetPieceIndex(Color.Black, (PieceType)piece)];
            }

            return(occupancy);
        }
Beispiel #7
0
        /// <summary>
        /// Calculates a position evaluation result for the specified parameters.
        /// </summary>
        /// <param name="bitboard">The bitboard.</param>
        /// <param name="color">The player color.</param>
        /// <returns>The position evaluation result.</returns>
        private int GetPosition(Bitboard bitboard, Color color)
        {
            var position = 0;

            for (var piece = 0; piece < 6; piece++)
            {
                var piecesToParse = bitboard.Pieces[FastArray.GetPieceIndex(color, (PieceType)piece)];
                position += GetPositionValue(bitboard, color, (PieceType)piece, piecesToParse);
            }

            return(position);
        }
        /// <summary>
        /// Gets a piece type on the specified field.
        /// </summary>
        /// <param name="field">The field with piece.</param>
        /// <param name="pieceColor">The piece color.</param>
        /// <param name="bitboard">The bitboard.</param>
        /// <exception cref="PieceTypeNotFoundException">Thrown when there is no piece on the specified field.</exception>
        /// <returns>The piece type on the specified field.</returns>
        private PieceType GetPieceType(ulong field, Color pieceColor, Bitboard bitboard)
        {
            for (var piece = 0; piece < 6; piece++)
            {
                if ((field & bitboard.Pieces[FastArray.GetPieceIndex(pieceColor, (PieceType)piece)]) != 0)
                {
                    return((PieceType)piece);
                }
            }

            throw new PieceTypeNotFoundException();
        }
Beispiel #9
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;
                }
            }
        }
        /// <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);
            }
        }
Beispiel #11
0
        /// <summary>
        /// Calculates a material evaluation result for the specified player by adding all piece values and
        /// multiplying them by the specified ratio.
        /// </summary>
        /// <param name="bitboard">The bitboard.</param>
        /// <param name="color">The player color.</param>
        /// <returns>The material evaluation result for the specified player.</returns>
        private int GetMaterialValue(Bitboard bitboard, Color color)
        {
            var material = 0;

            for (var piece = 0; piece < 6; piece++)
            {
                var piecesToParse = bitboard.Pieces[FastArray.GetPieceIndex(color, (PieceType)piece)];
                var piecesCount   = BitOperations.Count(piecesToParse);

                material += piecesCount * MaterialValues.PieceValues[piece];
            }

            return(material);
        }
        /// <summary>
        /// Gets a least valuable piece for the specified bitboard with field attackers.
        /// </summary>
        /// <param name="attackers">The bitboard with field attackers.</param>
        /// <param name="color">The color of a least valuable piece.</param>
        /// <param name="bitboard">The bitboard.</param>
        /// <returns>The least valuable piece (null if there is no more available pieces).</returns>
        private PieceType?GetAndPopLeastValuablePiece(ref ulong attackers, Color color, Bitboard bitboard)
        {
            for (var piece = 0; piece < 6; piece++)
            {
                var attackersWithType = attackers & bitboard.Pieces[FastArray.GetPieceIndex(color, (PieceType)piece)];

                if (attackersWithType != 0)
                {
                    var attackerLSB = BitOperations.GetLSB(attackersWithType);
                    attackers &= ~attackerLSB;

                    return((PieceType)piece);
                }
            }

            return(null);
        }
Beispiel #13
0
        /// <summary>
        /// Helper method for derived classes, calculates move with the specified parameters.
        /// </summary>
        /// <param name="bitboard">The bitboard.</param>
        /// <param name="pieceFrom">The source piece type.</param>
        /// <param name="from">The piece source position.</param>
        /// <param name="pieceTo">The destination piece type.</param>
        /// <param name="to">The piece destination position.</param>
        protected void CalculatePieceMove(Bitboard bitboard, PieceType pieceFrom, ulong from, PieceType pieceTo, ulong to)
        {
            bitboard.Pieces[FastArray.GetPieceIndex(Color, pieceFrom)] &= ~from;
            bitboard.Pieces[FastArray.GetPieceIndex(Color, pieceTo)]   |= to;
            bitboard.Occupancy[(int)Color] ^= from | to;

            IncrementalPosition.RemovePiece(bitboard, Color, pieceFrom, from);
            IncrementalPosition.AddPiece(bitboard, Color, pieceTo, to);

            IncrementalZobrist.AddOrRemovePiece(Color, pieceFrom, from, bitboard);
            IncrementalZobrist.AddOrRemovePiece(Color, pieceTo, to, bitboard);

            if (pieceFrom == PieceType.Pawn)
            {
                bitboard.ReversibleMoves = 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);
        }
Beispiel #15
0
        /// <summary>
        /// Removes killed piece from the specified bitboard.
        /// </summary>
        /// <param name="bitboard">The bitboard.</param>
        /// <param name="enemyColor">The enemy color.</param>
        /// <param name="fieldLSB">The bitboard with set field.</param>
        protected void CalculateKill(Bitboard bitboard, Color enemyColor, ulong fieldLSB)
        {
            for (var piece = 0; piece < 6; piece++)
            {
                var index = FastArray.GetPieceIndex(enemyColor, (PieceType)piece);
                if ((bitboard.Pieces[index] & fieldLSB) != 0)
                {
                    bitboard.Pieces[index] &= ~fieldLSB;
                    bitboard.Occupancy[(int)enemyColor] &= ~fieldLSB;

                    IncrementalMaterial.RemovePiece(bitboard, enemyColor, (PieceType)piece);
                    IncrementalPosition.RemovePiece(bitboard, enemyColor, (PieceType)piece, fieldLSB);
                    IncrementalZobrist.AddOrRemovePiece(enemyColor, (PieceType)piece, fieldLSB, bitboard);

                    bitboard.ReversibleMoves = 0;
                    break;
                }
            }
        }
Beispiel #16
0
        /// <summary>
        /// Calculates a chain evaluation result for the specified player by adding number of pawns
        /// in chains multiplied by the specified ratio.
        /// </summary>
        /// <param name="bitboard">The bitboard.</param>
        /// <param name="color">The player color.</param>
        /// <returns>The chain evaluation result for the specified player.</returns>
        public int GetChainValue(Bitboard bitboard, Color color)
        {
            var chain = 0;

            var pawns        = bitboard.Pieces[FastArray.GetPieceIndex(color, PieceType.Pawn)];
            var pawnsToParse = pawns;

            while (pawnsToParse != 0)
            {
                var pawnLSB = BitOperations.GetLSB(pawnsToParse);
                pawnsToParse = BitOperations.PopLSB(pawnsToParse);

                var chainMask = GetChainMask(color, pawnLSB);

                chain += BitOperations.Count(pawns & chainMask);
            }

            return(chain * PawnStructureValues.PawnChainRatio[(int)bitboard.GamePhase]);
        }
Beispiel #17
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;
                    }
                }
            }
        }
Beispiel #18
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));
            }
        }
        /// <summary>
        /// Calculates a doubled pawns evaluation result for the specified player by adding number of pawns
        /// on the same files.
        /// </summary>
        /// <param name="bitboard">The bitboard.</param>
        /// <param name="color">The player color.</param>
        /// <returns>The doubled pawns evaluation result for the specified player.</returns>
        public int GetDoubledPawnsValue(Bitboard bitboard, Color color)
        {
            var doubledPawns = 0;
            var pawns        = bitboard.Pieces[FastArray.GetPieceIndex(color, PieceType.Pawn)];

            for (var i = 0; i < 8; i++)
            {
                var file = BitConstants.HFile << i;

                var pawnsInFile = pawns & file;
                pawnsInFile = BitOperations.PopLSB(pawnsInFile);

                if (pawnsInFile != 0)
                {
                    doubledPawns += BitOperations.Count(pawnsInFile);
                }
            }

            return(doubledPawns * PawnStructureValues.DoubledPawnsRatio[(int)bitboard.GamePhase]);
        }
Beispiel #20
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));
                }
            }
        }
        /// <summary>
        /// Calculates a value of pieces that are attacking the neighbour fields of specified king.
        /// </summary>
        /// <param name="bitboard">The bitboard.</param>
        /// <param name="color">The king color.</param>
        /// <returns>The value of the pieces that are attacking king neighbour fields multiplied by the specified ratio.</returns>
        private int GetAttackedNeighboursValue(Bitboard bitboard, Color color)
        {
            var attackedNeighbours = 0;

            var king      = bitboard.Pieces[FastArray.GetPieceIndex(color, PieceType.King)];
            var kingIndex = BitOperations.GetBitIndex(king);
            var kingMoves = PatternsContainer.KingExpandedPattern[kingIndex];

            while (kingMoves != 0)
            {
                var fieldLSB = BitOperations.GetLSB(kingMoves);
                kingMoves = BitOperations.PopLSB(kingMoves);

                var fieldIndex = BitOperations.GetBitIndex(fieldLSB);
                var attacks    = bitboard.Attacks[fieldIndex] & ~bitboard.Occupancy[(int)color];

                attackedNeighbours += BitOperations.Count(attacks);
            }

            return(attackedNeighbours * KingSafetyValues.AttackedNeighboursRatio[(int)bitboard.GamePhase]);
        }
Beispiel #22
0
        /// <summary>
        /// Calculates a isolated pawns evaluation result for the specified player by adding number of pawns
        /// without any same-color pawns at neighbour files.
        /// </summary>
        /// <param name="bitboard">The bitboard.</param>
        /// <param name="color">The player color.</param>
        /// <returns>The isolated pawns evaluation result for the specified player.</returns>
        public int GetIsolatedPawnsValue(Bitboard bitboard, Color color)
        {
            var isolatedPawns = 0;
            var pawns         = bitboard.Pieces[FastArray.GetPieceIndex(color, PieceType.Pawn)];

            for (var i = 0; i < 8; i++)
            {
                var file = BitConstants.HFile << i;

                var pawnsInFile       = pawns & file;
                var previousLinePawns = pawns & ((file & ~BitConstants.AFile) << 1);
                var nextLinePawns     = pawns & ((file & ~BitConstants.HFile) >> 1);

                if (pawnsInFile != 0 && previousLinePawns == 0 && nextLinePawns == 0)
                {
                    isolatedPawns += BitOperations.Count(pawnsInFile);
                }
            }

            return(isolatedPawns * PawnStructureValues.IsolatedPawnsRatio[(int)bitboard.GamePhase]);
        }
Beispiel #23
0
        /// <summary>
        /// Gets a piece type on the specified field.
        /// </summary>
        /// <param name="field">The field with piece.</param>
        /// <param name="pieceColor">The piece color.</param>
        /// <param name="bitboard">The bitboard.</param>
        /// <exception cref="PieceTypeNotFoundException">Thrown when there is no piece on the specified field.</exception>
        /// <returns>The piece type on the specified field.</returns>
        private PieceType GetPieceType(ulong field, Color pieceColor, Bitboard bitboard)
        {
            for (var piece = 0; piece < 6; piece++)
            {
                if ((field & bitboard.Pieces[FastArray.GetPieceIndex(pieceColor, (PieceType)piece)]) != 0)
                {
                    return((PieceType)piece);
                }
            }

            // Temporary, there is a bug here
            Console.WriteLine(field);
            Console.WriteLine(pieceColor);
            Console.WriteLine(bitboard.Occupancy[0]);
            Console.WriteLine(bitboard.Occupancy[1]);
            Console.WriteLine(bitboard.AttacksSummary[0]);
            Console.WriteLine(bitboard.AttacksSummary[1]);
            Console.WriteLine(bitboard.VerifyIntegrity());
            Console.WriteLine(bitboard.Pieces[0]);
            Console.WriteLine(bitboard.Pieces[1]);
            Console.WriteLine(bitboard.Pieces[2]);
            Console.WriteLine(bitboard.Pieces[3]);
            Console.WriteLine(bitboard.Pieces[4]);
            Console.WriteLine(bitboard.Pieces[5]);
            Console.WriteLine(bitboard.Pieces[6]);
            Console.WriteLine(bitboard.Pieces[7]);
            Console.WriteLine(bitboard.Pieces[8]);
            Console.WriteLine(bitboard.Pieces[9]);
            Console.WriteLine(bitboard.Pieces[10]);
            Console.WriteLine(bitboard.Pieces[11]);

            var save = new BoardWriter();

            save.Write("err.board", new FriendlyBoard(bitboard));
            //

            throw new PieceTypeNotFoundException();
        }
        /// <summary>
        /// Calculates Zobrist hash for pieces.
        /// </summary>
        /// <param name="hash">The current hash.</param>
        /// <param name="pieces">The array of pieces.</param>
        /// <returns>The updated Zobrist hash.</returns>
        private static ulong CalculatePieces(ulong hash, ulong[] pieces)
        {
            for (var colorIndex = 0; colorIndex < 2; colorIndex++)
            {
                var color = (Color)colorIndex;
                for (var pieceIndex = 0; pieceIndex < 6; pieceIndex++)
                {
                    var piece       = (PieceType)pieceIndex;
                    var piecesArray = pieces[FastArray.GetPieceIndex(color, piece)];

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

                        var fieldIndex = BitOperations.GetBitIndex(pieceLSB);

                        hash ^= ZobristContainer.Pieces[FastArray.GetZobristPieceIndex(color, piece, fieldIndex)];
                    }
                }
            }

            return(hash);
        }
Beispiel #25
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);
 }
Beispiel #26
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);
 }