// Note that this doesn't check if a pawn can be taken en passant public bool IsAttacked(int defenderIx, Color defenderColor) { // check in roughly descending order of power // rook and queen var potentialRookCaptures = RookMoveTable.GetMoves(defenderIx, GetOccupied()); if ((potentialRookCaptures & GetPieceBitboard(defenderColor.Other(), PieceType.Rook)) > 0) { return(true); } if ((potentialRookCaptures & GetPieceBitboard(defenderColor.Other(), PieceType.Queen)) > 0) { return(true); } // bishop and queen var potentialBishopCaptures = BishopMoveTable.GetMoves(defenderIx, GetOccupied()); if ((potentialBishopCaptures & GetPieceBitboard(defenderColor.Other(), PieceType.Bishop)) > 0) { return(true); } if ((potentialBishopCaptures & GetPieceBitboard(defenderColor.Other(), PieceType.Queen)) > 0) { return(true); } var potentialKnightCaptures = KnightMoveTable.GetMoves(defenderIx); if ((potentialKnightCaptures & GetPieceBitboard(defenderColor.Other(), PieceType.Knight)) > 0) { return(true); } var potentialKingCaptures = KingMoveTable.GetMoves(defenderIx); if ((potentialKingCaptures & GetPieceBitboard(defenderColor.Other(), PieceType.King)) > 0) { return(true); } var potentialPawnCaptures = PawnCaptureMoveTable.GetMoves(defenderIx, defenderColor); if ((potentialPawnCaptures & GetPieceBitboard(defenderColor.Other(), PieceType.Pawn)) > 0) { return(true); } // we checked all possible attacks by all possible piece types return(false); }
private void GeneratePawnMoves(List <Move> moves, Position position, ulong sourceSquares) { var color = position.SideToMove; ulong promotionSourceSquares = sourceSquares & PawnPromotionSourceTable[(int)color]; ulong nonPromotionSourceSquares = sourceSquares & ~promotionSourceSquares; while (Bits.TryPopLsb(ref nonPromotionSourceSquares, out var sourceIx)) { // TODO: separate out normal moves from double moves. Normal moves use normal lookup table, double moves use magic lookup table var quiets = PawnQuietMoveTable.GetMoves(sourceIx, color); quiets &= ~position.GetOccupied(); var doubles = PawnDoubleMoveTable.GetMoves(sourceIx, position.GetOccupied(), color); // note: no need to mask double moves; the move table already takes care of that var captures = PawnCaptureMoveTable.GetMoves(sourceIx, color); var normalCaptures = captures & position.GetOccupied(color.Other()); var enPassantCaptures = captures & position.EnPassant; while (Bits.TryPopLsb(ref quiets, out var dstIx)) { moves.Add(new Move(MoveType.Normal | MoveType.Quiet, sourceIx, dstIx)); } while (Bits.TryPopLsb(ref doubles, out var dstIx)) { moves.Add(new Move(MoveType.DoubleMove | MoveType.Quiet, sourceIx, dstIx)); } while (Bits.TryPopLsb(ref normalCaptures, out var dstIx)) { moves.Add(new Move(MoveType.Normal | MoveType.Capture, sourceIx, dstIx)); } while (Bits.TryPopLsb(ref enPassantCaptures, out var dstIx)) { moves.Add(new Move(MoveType.EnPassant | MoveType.Capture, sourceIx, dstIx)); } } while (Bits.TryPopLsb(ref promotionSourceSquares, out var sourceIx)) { var quiets = PawnQuietMoveTable.GetMoves(sourceIx, color); quiets &= ~position.GetOccupied(); var captures = PawnCaptureMoveTable.GetMoves(sourceIx, color); captures &= position.GetOccupied(color.Other()); foreach (var piece in new[] { PieceType.Queen, PieceType.Knight, PieceType.Rook, PieceType.Bishop }) { var quietsTmp = quiets; while (Bits.TryPopLsb(ref quietsTmp, out var dstIx)) { moves.Add(new Move(MoveType.Promotion | MoveType.Quiet, sourceIx, dstIx, piece)); } var capturesTmp = captures; while (Bits.TryPopLsb(ref capturesTmp, out var dstIx)) { moves.Add(new Move(MoveType.Promotion | MoveType.Capture, sourceIx, dstIx, piece)); } } } }