Exemple #1
0
        private static void Perft(BoardState boardState, int depth, AdvancedPerftResult result)
        {
            Span <Move> moves      = stackalloc Move[SearchConstants.MaxMovesCount];
            var         movesCount = boardState.GetAllMoves(moves);

            if (depth <= 0)
            {
                result.Leafs++;
                return;
            }

            if (depth == 1)
            {
                UpdateResult(boardState, moves, movesCount, result);
                return;
            }

            for (var i = 0; i < movesCount; i++)
            {
                boardState.MakeMove(moves[i]);
                if (!boardState.IsKingChecked(ColorOperations.Invert(boardState.ColorToMove)))
                {
                    Perft(boardState, depth - 1, result);
                }
                boardState.UndoMove(moves[i]);
            }
        }
Exemple #2
0
        /// <summary>
        /// Checks if the specified bitboard is finished or not.
        /// </summary>
        /// <param name="bitboard">The bitboard to check.</param>
        private void CheckIfGameHasEnded(Bitboard bitboard)
        {
            var enemyColor = ColorOperations.Invert(_currentColor);

            if (Bitboard.IsStalemate(enemyColor))
            {
                ConsoleManager.WriteLine("$gStalemate, wins!");
                _done = true;
                return;
            }

            if (Bitboard.IsThreefoldRepetition())
            {
                ConsoleManager.WriteLine("$gThreefold repetition!");
                _done = true;
                return;
            }

            if (Bitboard.IsMate(enemyColor))
            {
                ConsoleManager.WriteLine($"$gMate, {_currentColor} wins!");
                _done = true;
                return;
            }
        }
Exemple #3
0
        public static int GetLoudMoves(BoardState boardState, Span <Move> moves, int offset, ulong evasionMask)
        {
            var color      = boardState.ColorToMove;
            var enemyColor = ColorOperations.Invert(color);
            var queens     = boardState.Pieces[color][Piece.Queen];

            while (queens != 0)
            {
                var piece = BitOperations.GetLsb(queens);
                queens = BitOperations.PopLsb(queens);

                var from           = BitOperations.BitScan(piece);
                var availableMoves = QueenMovesGenerator.GetMoves(boardState.OccupancySummary, from) & boardState.Occupancy[enemyColor];
                availableMoves &= evasionMask;

                while (availableMoves != 0)
                {
                    var field      = BitOperations.GetLsb(availableMoves);
                    var fieldIndex = BitOperations.BitScan(field);
                    availableMoves = BitOperations.PopLsb(availableMoves);

                    moves[offset++] = new Move(from, fieldIndex, MoveFlags.Capture);
                }
            }

            return(offset);
        }
Exemple #4
0
        private static ulong Perft(BoardState boardState, int depth, ref bool verificationSuccess)
        {
            if (!VerifyBoard(boardState))
            {
                verificationSuccess = false;
                return(0);
            }

            if (depth <= 0)
            {
                return(1);
            }

            Span <Move> moves      = stackalloc Move[SearchConstants.MaxMovesCount];
            var         movesCount = boardState.GetAllMoves(moves);

            ulong nodes = 0;

            for (var i = 0; i < movesCount; i++)
            {
                boardState.MakeNullMove();
                boardState.UndoNullMove();

                boardState.MakeMove(moves[i]);
                if (!boardState.IsKingChecked(ColorOperations.Invert(boardState.ColorToMove)))
                {
                    nodes += Perft(boardState, depth - 1, ref verificationSuccess);
                }
                boardState.UndoMove(moves[i]);
            }

            return(nodes);
        }
Exemple #5
0
        /// <summary>
        /// Does an AI move.
        /// </summary>
        private void MoveAI()
        {
            Task.Run(() =>
            {
                var openingBookMove = _openingBook.GetMoveFromBook(_history);
                var enemyColor      = ColorOperations.Invert(_currentColor);

                Move moveToApply = null;

                if (openingBookMove != null)
                {
                    moveToApply = Bitboard.Moves.First(p =>
                                                       p.From == openingBookMove.From && p.To == openingBookMove.To);
                }
                else
                {
                    var aiResult = _ai.Calculate(_currentColor, Bitboard, _preferredTime, _helperTasksCount);
                    moveToApply  = aiResult.PVNodes[0];

                    ConsoleManager.WriteLine();
                    ConsoleManager.WriteLine($"$w{_currentColor}:");
                    ConsoleManager.WriteLine($"$wBest move: $g{aiResult.PVNodes} $w(Score: $m{aiResult.Score}$w)");
                    ConsoleManager.WriteLine($"$wTotal nodes: $g{aiResult.Stats.TotalNodes} N $w(Depth: $m{aiResult.Depth}$w)");
                    ConsoleManager.WriteLine($"$wTime: $m{aiResult.Time} s");
                    ConsoleManager.WriteLine();
                }

                CalculateBitboard(moveToApply, false);

                CheckIfGameHasEnded(Bitboard);

                _currentColor = enemyColor;
                _history.Add(moveToApply);
            });
        }
Exemple #6
0
        public static int GetQuietMoves(BoardState boardState, Span <Move> moves, int offset, ulong evasionMask)
        {
            var color      = boardState.ColorToMove;
            var enemyColor = ColorOperations.Invert(color);
            var knights    = boardState.Pieces[color][Piece.Knight];

            while (knights != 0)
            {
                var piece = BitOperations.GetLsb(knights);
                knights = BitOperations.PopLsb(knights);

                var from           = BitOperations.BitScan(piece);
                var availableMoves = KnightMovesGenerator.GetMoves(from) & ~boardState.OccupancySummary;
                availableMoves &= evasionMask;

                while (availableMoves != 0)
                {
                    var field      = BitOperations.GetLsb(availableMoves);
                    var fieldIndex = BitOperations.BitScan(field);
                    availableMoves = BitOperations.PopLsb(availableMoves);

                    moves[offset++] = new Move(from, fieldIndex, MoveFlags.Quiet);
                }
            }

            return(offset);
        }
        private static int GetPrincipalVariation(BoardState board, Move[] moves, int movesCount)
        {
            var entry = TranspositionTable.Get(board.Hash);

            if (entry.Flags == TranspositionTableEntryFlags.ExactScore && entry.IsKeyValid(board.Hash) && movesCount < SearchConstants.MaxDepth)
            {
                if (!board.IsMoveLegal(entry.BestMove))
                {
                    return(movesCount);
                }

                moves[movesCount] = entry.BestMove;
                board.MakeMove(entry.BestMove);

                var enemyColor = ColorOperations.Invert(board.ColorToMove);
                var king       = board.Pieces[enemyColor][Piece.King];
                var kingField  = BitOperations.BitScan(king);

                if (board.IsFieldAttacked(enemyColor, (byte)kingField))
                {
                    board.UndoMove(entry.BestMove);
                    return(movesCount);
                }

                movesCount = GetPrincipalVariation(board, moves, movesCount + 1);
                board.UndoMove(entry.BestMove);
            }

            return(movesCount);
        }
Exemple #8
0
        public bool IsFieldPassing(int color, int field)
        {
            var enemyColor  = ColorOperations.Invert(color);
            var passingArea = PassingPatternGenerator.GetPattern(color, field);

            return((passingArea & Pieces[enemyColor][Piece.Pawn]) == 0);
        }
Exemple #9
0
        public static int GetAvailableCaptureMoves(BoardState boardState, Span <Move> moves, int offset)
        {
            var color      = boardState.ColorToMove;
            var enemyColor = ColorOperations.Invert(color);
            var rooks      = boardState.Pieces[color][Piece.Rook];

            while (rooks != 0)
            {
                var piece = BitOperations.GetLsb(rooks);
                rooks = BitOperations.PopLsb(rooks);

                var from           = BitOperations.BitScan(piece);
                var availableMoves = RookMovesGenerator.GetMoves(boardState.OccupancySummary, from) & boardState.Occupancy[enemyColor];

                while (availableMoves != 0)
                {
                    var field      = BitOperations.GetLsb(availableMoves);
                    var fieldIndex = BitOperations.BitScan(field);
                    availableMoves = BitOperations.PopLsb(availableMoves);

                    moves[offset++] = new Move(from, fieldIndex, MoveFlags.Capture);
                }
            }

            return(offset);
        }
Exemple #10
0
        public static int GetQuietMoves(BoardState boardState, Span <Move> moves, int offset)
        {
            var color      = boardState.ColorToMove;
            var enemyColor = ColorOperations.Invert(color);
            var piece      = boardState.Pieces[color][Piece.King];

            if (piece == 0)
            {
                return(offset);
            }

            var from           = BitOperations.BitScan(piece);
            var availableMoves = KingMovesGenerator.GetMoves(from) & ~boardState.OccupancySummary;

            while (availableMoves != 0)
            {
                var field      = BitOperations.GetLsb(availableMoves);
                var fieldIndex = BitOperations.BitScan(field);
                availableMoves = BitOperations.PopLsb(availableMoves);

                moves[offset++] = new Move(from, fieldIndex, MoveFlags.Quiet);
            }

            return(offset);
        }
Exemple #11
0
        private static bool LMRCanBeApplied(SearchContext context, int depth, bool friendlyKingInCheck, bool enemyKingInCheck, int moveIndex, Span <Move> moves, Span <short> moveValues)
        {
            if (depth >= SearchConstants.LMRMinDepth && moveIndex >= SearchConstants.LMRMovesWithoutReduction &&
                (moves[moveIndex].IsQuiet() || (moves[moveIndex].IsCapture() && moveValues[moveIndex] < 0)) && !friendlyKingInCheck && !enemyKingInCheck)
            {
                var enemyColor = ColorOperations.Invert(context.BoardState.ColorToMove);
                var piece      = context.BoardState.PieceTable[moves[moveIndex].To];

                if (HistoryHeuristic.GetRawMoveValue(enemyColor, piece, moves[moveIndex].To) >= HistoryHeuristic.GetMaxValue() / SearchConstants.LMRMaxHistoryValueDivider)
                {
                    return(false);
                }

                if (piece == Piece.Pawn && context.BoardState.IsFieldPassing(enemyColor, moves[moveIndex].To))
                {
                    return(false);
                }

#if DEBUG
                context.Statistics.LMRReductions++;
#endif

                return(true);
            }

            return(false);
        }
Exemple #12
0
        /// <summary>
        /// Calculates en passant move.
        /// </summary>
        /// <param name="bitboard">The bitboard.</param>
        public override void CalculateMove(Bitboard bitboard)
        {
            var from       = BitPositionConverter.ToULong(From);
            var to         = BitPositionConverter.ToULong(To);
            var enemyColor = ColorOperations.Invert(Color);

            RemoveEnPassantPiece(bitboard, enemyColor, to);
            CalculatePieceMove(bitboard, from, to);
        }
Exemple #13
0
        public int Do(Color color, Bitboard bitboard, int alpha, int beta, AIStats stats)
        {
            var enemyColor = ColorOperations.Invert(color);
            var colorSign  = ColorOperations.ToSign(color);

            stats.QuiescenceTotalNodes++;

            var whiteGeneratorMode = GetGeneratorMode(color, Color.White);
            var blackGeneratorMode = GetGeneratorMode(color, Color.Black);

            bitboard.Calculate(whiteGeneratorMode, blackGeneratorMode, true);

            if (bitboard.IsCheck(enemyColor))
            {
                stats.QuiescenceEndNodes++;
                return(AIConstants.MateValue);
            }

            var evaluation = colorSign * bitboard.GetEvaluation();

            if (evaluation >= beta)
            {
                stats.QuiescenceEndNodes++;
                return(beta);
            }

            if (evaluation > alpha)
            {
                alpha = evaluation;
            }

            var sortedMoves = SortMoves(color, bitboard, bitboard.Moves);

            foreach (var move in sortedMoves)
            {
                var bitboardAfterMove = bitboard.Move(move);
                var nodeValue         = -Do(enemyColor, bitboardAfterMove, -beta, -alpha, stats);

                if (nodeValue >= beta)
                {
                    return(beta);
                }

                if (nodeValue > alpha)
                {
                    alpha = nodeValue;
                }
            }

            if (!sortedMoves.Any())
            {
                stats.QuiescenceEndNodes++;
            }

            return(alpha);
        }
        /// <summary>
        /// Initializes a new instance of the <see cref="Bitboard"/> class.
        /// </summary>
        /// <param name="bitboard">The previous bitboard.</param>
        /// <param name="move">The move to apply.</param>
        public Bitboard(Bitboard bitboard, Move move) : this(bitboard)
        {
            IncrementalZobrist.ClearEnPassant(ColorOperations.Invert(move.Color), this);

            EnPassant[(int)ColorOperations.Invert(move.Color)] = 0;
            ReversibleMoves++;

            move.Do(this);

            CalculateGamePhase();
            UpdateHistory();
        }
        /// <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);
        }
Exemple #16
0
        public void UndoNullMove()
        {
            NullMoves--;
            ColorToMove = ColorOperations.Invert(ColorToMove);

            Hash      = _hashes.Pop();
            EnPassant = _enPassants.Pop();

            if (ColorToMove == Color.White)
            {
                MovesCount--;
            }
        }
Exemple #17
0
        public static int GetLoudMoves(BoardState boardState, Span <Move> moves, int offset)
        {
            var color      = boardState.ColorToMove;
            var enemyColor = ColorOperations.Invert(color);
            var piece      = boardState.Pieces[color][Piece.King];

            if (piece == 0)
            {
                return(offset);
            }

            var from           = BitOperations.BitScan(piece);
            var availableMoves = KingMovesGenerator.GetMoves(from) & boardState.Occupancy[enemyColor];

            while (availableMoves != 0)
            {
                var field      = BitOperations.GetLsb(availableMoves);
                var fieldIndex = BitOperations.BitScan(field);
                availableMoves = BitOperations.PopLsb(availableMoves);

                moves[offset++] = new Move(from, fieldIndex, MoveFlags.Capture);
            }

            if (color == Color.White)
            {
                if (IsWhiteKingCastlingAvailable(boardState, color))
                {
                    moves[offset++] = new Move(3, 1, MoveFlags.KingCastle);
                }

                if (IsWhiteQueenCastlingAvailable(boardState, color))
                {
                    moves[offset++] = new Move(3, 5, MoveFlags.QueenCastle);
                }
            }
            else
            {
                if (IsBlackKingCastlingAvailable(boardState, color))
                {
                    moves[offset++] = new Move(59, 57, MoveFlags.KingCastle);
                }

                if (IsBlackQueenCastlingAvailable(boardState, color))
                {
                    moves[offset++] = new Move(59, 61, MoveFlags.QueenCastle);
                }
            }

            return(offset);
        }
Exemple #18
0
        public static int Evaluate(BoardState board, int color, int openingPhase, int endingPhase)
        {
            var doubledRooks    = 0;
            var rooksOnOpenFile = 0;
            var pairOfBishops   = 0;
            var enemyColor      = ColorOperations.Invert(color);

            var rooks = board.Pieces[color][Piece.Rook];

            while (rooks != 0)
            {
                var lsb   = BitOperations.GetLsb(rooks);
                var field = BitOperations.BitScan(lsb);
                rooks = BitOperations.PopLsb(rooks);

                var file                = FilePatternGenerator.GetPattern(field) | lsb;
                var rooksOnFile         = file & board.Pieces[color][Piece.Rook];
                var friendlyPawnsOnFile = file & board.Pieces[color][Piece.Pawn];
                var enemyPawnsOnFile    = file & board.Pieces[enemyColor][Piece.Pawn];

                if (BitOperations.Count(rooksOnFile) > 1)
                {
                    // We don't assume that there will be more than two rooks - even if, then this color is probably anyway winning
                    doubledRooks = 1;
                }

                if (friendlyPawnsOnFile == 0 && enemyPawnsOnFile == 0)
                {
                    rooksOnOpenFile++;
                }
            }

            var bishops = board.Pieces[color][Piece.Bishop];

            if (BitOperations.Count(bishops) > 1)
            {
                pairOfBishops = 1;
            }

            var doubledRooksOpeningScore = doubledRooks * EvaluationConstants.DoubledRooks;
            var doubledRooksAdjusted     = TaperedEvaluation.AdjustToPhase(doubledRooksOpeningScore, 0, openingPhase, endingPhase);

            var rooksOnOpenFileOpeningScore = rooksOnOpenFile * EvaluationConstants.RookOnOpenFile;
            var rooksOnOpenFileAdjusted     = TaperedEvaluation.AdjustToPhase(rooksOnOpenFileOpeningScore, 0, openingPhase, endingPhase);

            var pairOfBishopsOpeningScore = pairOfBishops * EvaluationConstants.PairOfBishops;
            var pairOfBishopsAdjusted     = TaperedEvaluation.AdjustToPhase(pairOfBishopsOpeningScore, 0, openingPhase, endingPhase);

            return(doubledRooksAdjusted + rooksOnOpenFileAdjusted + pairOfBishopsAdjusted);
        }
Exemple #19
0
        public bool IsFieldAttacked(int color, int fieldIndex)
        {
            var enemyColor = ColorOperations.Invert(color);

            var fileRankAttacks = RookMovesGenerator.GetMoves(OccupancySummary, fieldIndex) & Occupancy[enemyColor];
            var attackingRooks  = fileRankAttacks & (Pieces[enemyColor][Piece.Rook] | Pieces[enemyColor][Piece.Queen]);

            if (attackingRooks != 0)
            {
                return(true);
            }

            var diagonalAttacks  = BishopMovesGenerator.GetMoves(OccupancySummary, fieldIndex) & Occupancy[enemyColor];
            var attackingBishops = diagonalAttacks & (Pieces[enemyColor][Piece.Bishop] | Pieces[enemyColor][Piece.Queen]);

            if (attackingBishops != 0)
            {
                return(true);
            }

            var jumpAttacks      = KnightMovesGenerator.GetMoves(fieldIndex);
            var attackingKnights = jumpAttacks & Pieces[enemyColor][Piece.Knight];

            if (attackingKnights != 0)
            {
                return(true);
            }

            var boxAttacks     = KingMovesGenerator.GetMoves(fieldIndex);
            var attackingKings = boxAttacks & Pieces[enemyColor][Piece.King];

            if (attackingKings != 0)
            {
                return(true);
            }

            var field          = 1ul << fieldIndex;
            var potentialPawns = boxAttacks & Pieces[enemyColor][Piece.Pawn];
            var attackingPawns = color == Color.White ?
                                 field & ((potentialPawns >> 7) | (potentialPawns >> 9)) :
                                 field & ((potentialPawns << 7) | (potentialPawns << 9));

            if (attackingPawns != 0)
            {
                return(true);
            }

            return(false);
        }
Exemple #20
0
        /// <summary>
        /// Calculates a promotion move.
        /// </summary>
        /// <param name="bitboard">The bitboard.</param>
        public override void CalculateMove(Bitboard bitboard)
        {
            var from = BitPositionConverter.ToULong(From);
            var to   = BitPositionConverter.ToULong(To);

            if (KillMove)
            {
                CalculateKill(bitboard, ColorOperations.Invert(Color), to);
            }

            CalculatePieceMove(bitboard, Piece, from, PromotionPiece, to);

            IncrementalMaterial.RemovePiece(bitboard, Color, Piece);
            IncrementalMaterial.AddPiece(bitboard, Color, PromotionPiece);
        }
Exemple #21
0
        /// <summary>
        /// The event handler for OnFieldSelection.
        /// </summary>
        /// <param name="sender">The event sender.</param>
        /// <param name="e">The event arguments.</param>
        private void Board_OnFieldSelection(object sender, FieldSelectedEventArgs e)
        {
            if (!_done && _currentColor == _playerColor && e.Piece != null && e.Piece.Color == _currentColor)
            {
                var enemyColor = ColorOperations.Invert(_currentColor);

                var movesForPiece = Bitboard.Moves
                                    .Where(p => p.From == e.Position && !Bitboard.Moves.Any(q => p.Piece == PieceType.King &&
                                                                                            q.Color == enemyColor && q.To == p.To))
                                    .Select(p => p.To)
                                    .ToList();

                VisualBoard.AddExternalSelections(movesForPiece);
            }
        }
Exemple #22
0
        /// <summary>
        /// The event handler for OnPieceMove.
        /// </summary>
        /// <param name="sender">The event sender.</param>
        /// <param name="e">The event arguments.</param>
        private void Board_OnPieceMove(object sender, PieceMovedEventArgs e)
        {
            if (!_done && _currentColor == _playerColor && e.Piece != null && e.Piece.Color == _currentColor)
            {
                var enemyColor = ColorOperations.Invert(_currentColor);

                var move = Bitboard.Moves.FirstOrDefault(p => p.From == e.From && p.To == e.To);

                if (move == null)
                {
                    return;
                }

                var testBitboard = Bitboard.Move(move);
                testBitboard.Calculate(false);

                if (testBitboard.IsCheck(_currentColor))
                {
                    ConsoleManager.WriteLine("$RInvalid move");
                    return;
                }

                switch (move)
                {
                case PromotionMove _:
                {
                    var promotionMoves = Bitboard.Moves.OfType <PromotionMove>().Where(p => p.From == move.From &&
                                                                                       p.To == move.To);
                    PromotionWindow.Display(move.Color, promotionMoves);

                    break;
                }

                default:
                {
                    CalculateBitboard(move, false);
                    break;
                }
                }

                CheckIfGameHasEnded(Bitboard);

                _currentColor = ColorOperations.Invert(_currentColor);
                _history.Add(move);

                MoveAI();
            }
        }
        /// <summary>
        /// Calculates SEE for the specified bitboard. All fields that are attacked by the passed color will be processed.
        /// </summary>
        /// <param name="initialColor">The color of the first attacker.</param>
        /// <param name="bitboard">The bitboard.</param>
        /// <returns>The list of all attacked fields with associated scores (relative to the first color attacker).</returns>
        public LinkedList <SEEResult> Calculate(Color initialColor, Bitboard bitboard)
        {
            var seeResults = new LinkedList <SEEResult>();

            var enemyColor      = ColorOperations.Invert(initialColor);
            var possibleAttacks = bitboard.AttacksSummary[(int)initialColor] & bitboard.Occupancy[(int)enemyColor];

            while (possibleAttacks != 0)
            {
                var field = BitOperations.GetLSB(possibleAttacks);
                possibleAttacks = BitOperations.PopLSB(possibleAttacks);

                RunSEEForField(field, initialColor, bitboard, seeResults);
            }

            return(seeResults);
        }
        private void ParseMoves(List <string> moves)
        {
            var color = Color.White;

            foreach (var move in moves)
            {
                var parsedMove = Move.FromTextNotation(_uciClient.BoardState, move);
                if (parsedMove == Move.Empty)
                {
                    _uciClient.SendError("invalidmove");
                    return;
                }

                _uciClient.BoardState.MakeMove(parsedMove);
                color = ColorOperations.Invert(color);
            }
        }
        public static bool IsMoveLegal(BoardState boardState, Move move)
        {
            var enemyColor = ColorOperations.Invert(boardState.ColorToMove);
            var toField    = 1ul << move.To;

            if (!move.IsCapture())
            {
                if (move.Flags == MoveFlags.Quiet || ((int)move.Flags & MoveFlagFields.Promotion) != 0)
                {
                    if ((boardState.OccupancySummary & toField) == 0)
                    {
                        return(true);
                    }
                }
                else if (move.Flags == MoveFlags.DoublePush)
                {
                    var middleField = 1ul << ((move.From + move.To) / 2);
                    if ((boardState.OccupancySummary & middleField) == 0 && (boardState.OccupancySummary & toField) == 0)
                    {
                        return(true);
                    }
                }
            }
            else
            {
                if (move.Flags == MoveFlags.EnPassant)
                {
                    if ((boardState.EnPassant & toField) != 0)
                    {
                        return(true);
                    }
                }
                else
                {
                    var difference      = move.To - move.From;
                    var colorDifference = -(boardState.ColorToMove * 2 - 1) * difference;

                    if ((boardState.Occupancy[enemyColor] & toField) != 0 && (colorDifference == 7 || colorDifference == 9))
                    {
                        return(true);
                    }
                }
            }

            return(false);
        }
        /// <summary>
        /// Calculates generator parameters for the specified player and generator mode.
        /// </summary>
        /// <param name="color">The player color.</param>
        /// <param name="mode">The generator mode.</param>
        /// <param name="quiescenceSearch">If true, only quiescence moves (mainly captures) will be generated.</param>
        /// <returns>The generator parameters.</returns>
        private GeneratorParameters GetGeneratorParameters(Color color, GeneratorMode mode, bool quiescenceSearch)
        {
            return(new GeneratorParameters
            {
                Bitboard = this,

                FriendlyColor = color,
                EnemyColor = ColorOperations.Invert(color),
                Mode = mode,

                OccupancySummary = Occupancy[(int)Color.White] | Occupancy[(int)Color.Black],
                FriendlyOccupancy = Occupancy[(int)color],
                EnemyOccupancy = Occupancy[(int)ColorOperations.Invert(color)],

                QuiescenceSearch = quiescenceSearch
            });
        }
Exemple #27
0
        public static bool IsMoveLegal(BoardState boardState, Move move)
        {
            var enemyColor     = ColorOperations.Invert(boardState.ColorToMove);
            var availableMoves = QueenMovesGenerator.GetMoves(boardState.OccupancySummary, move.From);
            var toField        = 1ul << move.To;

            if (move.IsSinglePush() && (availableMoves & toField) != 0 && (boardState.OccupancySummary & toField) == 0)
            {
                return(true);
            }

            if (move.IsCapture() && (availableMoves & toField) != 0 && (boardState.Occupancy[enemyColor] & toField) != 0)
            {
                return(true);
            }

            return(false);
        }
        public static bool IsMoveLegal(BoardState boardState, Move move)
        {
            var enemyColor     = ColorOperations.Invert(boardState.ColorToMove);
            var availableMoves = BishopMovesGenerator.GetMoves(boardState.OccupancySummary, move.From);
            var toField        = 1ul << move.To;

            if (move.Flags == MoveFlags.Quiet && (availableMoves & toField) != 0 && (boardState.OccupancySummary & toField) == 0)
            {
                return(true);
            }

            if (move.Flags == MoveFlags.Capture && (availableMoves & toField) != 0 && (boardState.Occupancy[enemyColor] & toField) != 0)
            {
                return(true);
            }

            return(false);
        }
Exemple #29
0
        private static void UpdateResult(BoardState boardState, Span <Move> moves, int movesCount, AdvancedPerftResult result)
        {
            var legalMoveFound = false;

            for (var i = 0; i < movesCount; i++)
            {
                boardState.MakeMove(moves[i]);

                if (!boardState.IsKingChecked(ColorOperations.Invert(boardState.ColorToMove)))
                {
                    if (moves[i].IsCapture())
                    {
                        result.Captures++;
                    }

                    if (moves[i].Flags == MoveFlags.KingCastle || moves[i].Flags == MoveFlags.QueenCastle)
                    {
                        result.Castles++;
                    }

                    if (moves[i].Flags == MoveFlags.EnPassant)
                    {
                        result.EnPassants++;
                        result.Captures++;
                    }

                    if (boardState.IsKingChecked(boardState.ColorToMove))
                    {
                        result.Checks++;
                    }

                    result.Leafs++;
                    legalMoveFound = true;
                }

                boardState.UndoMove(moves[i]);
            }

            if (!legalMoveFound)
            {
                result.Checkmates++;
            }
        }
Exemple #30
0
        public static bool IsMoveLegal(BoardState boardState, Move move)
        {
            var enemyColor     = ColorOperations.Invert(boardState.ColorToMove);
            var availableMoves = KingMovesGenerator.GetMoves(move.From);
            var toField        = 1ul << move.To;

            if (move.Flags == MoveFlags.Quiet && (availableMoves & toField) != 0 && (boardState.OccupancySummary & toField) == 0)
            {
                return(true);
            }

            if (move.Flags == MoveFlags.Capture && (availableMoves & toField) != 0 && (boardState.Occupancy[enemyColor] & toField) != 0)
            {
                return(true);
            }

            if (move.Flags == MoveFlags.KingCastle)
            {
                if (boardState.ColorToMove == Color.White && IsWhiteKingCastlingAvailable(boardState, boardState.ColorToMove))
                {
                    return(true);
                }
                else if (boardState.ColorToMove == Color.Black && IsBlackKingCastlingAvailable(boardState, boardState.ColorToMove))
                {
                    return(true);
                }
            }

            if (move.Flags == MoveFlags.QueenCastle)
            {
                if (boardState.ColorToMove == Color.White && IsWhiteQueenCastlingAvailable(boardState, boardState.ColorToMove))
                {
                    return(true);
                }
                else if (boardState.ColorToMove == Color.Black && IsBlackQueenCastlingAvailable(boardState, boardState.ColorToMove))
                {
                    return(true);
                }
            }

            return(false);
        }