Beispiel #1
0
        private readonly unsafe PooledList <Move> LoadCaptures()
        {
            var      opposingSide = _activeSide.Flip();
            Bitboard occupied     = _bbs.Occupies[0] | _bbs.Occupies[1];

            var result = PooledList <Move> .Get(16);

            // Loop over all pieces that can be captured, from most to least valuable
            for (var victimKind = PieceKind.Queen; victimKind >= PieceKind.Pawn; victimKind--)
            {
                var victim = new Piece(opposingSide, victimKind);
                for (Bitboard ds = _bbs.PiecePlacement[victim.ToIndex()]; !ds.IsZero; ds = ds.ClearNext())
                {
                    var destination = ds.NextLocation();
                    Debug.Assert(_board[destination].HasPiece && _board[destination].Piece == victim);

                    // Loop over all pieces that can capture at `destination`, from least to most valuable
                    Bitboard activeAttacks = _bbs.Attacks[(int)_activeSide];
                    if (activeAttacks[destination])
                    {
                        for (var aggKind = PieceKind.Pawn; aggKind <= PieceKind.King; aggKind++)
                        {
                            var agg = new Piece(_activeSide, aggKind);
                            for (Bitboard ss = _bbs.PiecePlacement[agg.ToIndex()]; !ss.IsZero; ss = ss.ClearNext())
                            {
                                var source = ss.NextLocation();
                                Debug.Assert(_board[source].HasPiece && _board[source].Piece == agg);

                                var sourceAttacks = GetAttackBitboard(_board[source].Piece, source, occupied);
                                if (sourceAttacks[destination])
                                {
                                    bool isPromotion = (aggKind == PieceKind.Pawn && source.Rank == SeventhRank(_activeSide));
                                    if (isPromotion)
                                    {
                                        result.Add(new Move(source, destination, promotionKind: PieceKind.Queen));
                                        result.Add(new Move(source, destination, promotionKind: PieceKind.Knight));
                                        result.Add(new Move(source, destination, promotionKind: PieceKind.Rook));
                                        result.Add(new Move(source, destination, promotionKind: PieceKind.Bishop));
                                    }
                                    else
                                    {
                                        result.Add(new Move(source, destination));
                                    }
                                }
                            }
                        }
                    }

                    // En passant captures need to be handled specially
                    if (_enPassantTarget is Location epTarget)
                    {
                        bool canBeCapturedEp = (destination == epTarget.Up(ForwardStep(opposingSide)));
                        if (canBeCapturedEp)
                        {
                            Debug.Assert(victimKind == PieceKind.Pawn);

                            Bitboard pawnPlacement = _bbs.PiecePlacement[new Piece(_activeSide, PieceKind.Pawn).ToIndex()];
                            if (destination.File > File.FileA && pawnPlacement[destination.Left(1)])
                            {
                                result.Add(new Move(destination.Left(1), epTarget));
                            }
                            if (destination.File < File.FileH && pawnPlacement[destination.Right(1)])
                            {
                                result.Add(new Move(destination.Right(1), epTarget));
                            }
                        }
                    }
                }
            }

            return(result);
        }