private readonly unsafe PooledList <Move> LoadNonCaptures() { var result = PooledList <Move> .Get(32); for (Bitboard ss = _bbs.Occupies[(int)_activeSide]; !ss.IsZero; ss = ss.ClearNext()) { var source = ss.NextLocation(); var piece = _board[source].Piece; for (Bitboard ds = GetNonCaptureDestinations(source); !ds.IsZero; ds = ds.ClearNext()) { var destination = ds.NextLocation(); bool isPromotion = (piece.Kind == 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)); } } } return(result); }
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); }