private void GenerateQueenMoves(MoveGeneration MoveGeneration, ulong FromSquareMask, ulong ToSquareMask) { ulong queens; ulong unOrEnemyOccupiedSquares; ulong enemyOccupiedSquares; int attacker; if (WhiteMove) { // White Move queens = WhiteQueens & FromSquareMask; unOrEnemyOccupiedSquares = ~OccupancyWhite; enemyOccupiedSquares = OccupancyBlack; attacker = Piece.WhiteQueen; } else { // Black Move queens = BlackQueens & FromSquareMask; unOrEnemyOccupiedSquares = ~OccupancyBlack; enemyOccupiedSquares = OccupancyWhite; attacker = Piece.BlackQueen; } int fromSquare; while ((fromSquare = Bitwise.FindFirstSetBit(queens)) != Square.Illegal) { var bishopOccupancy = Board.BishopMoveMasks[fromSquare] & Occupancy; var rookOccupancy = Board.RookMoveMasks[fromSquare] & Occupancy; var queenDestinations = MoveGeneration switch { MoveGeneration.AllMoves => (Board.PrecalculatedMoves.GetBishopMovesMask(fromSquare, bishopOccupancy) | Board.PrecalculatedMoves.GetRookMovesMask(fromSquare, rookOccupancy)) & unOrEnemyOccupiedSquares & ToSquareMask, MoveGeneration.OnlyCaptures => (Board.PrecalculatedMoves.GetBishopMovesMask(fromSquare, bishopOccupancy) | Board.PrecalculatedMoves.GetRookMovesMask(fromSquare, rookOccupancy)) & enemyOccupiedSquares & ToSquareMask, MoveGeneration.OnlyNonCaptures => (Board.PrecalculatedMoves.GetBishopMovesMask(fromSquare, bishopOccupancy) | Board.PrecalculatedMoves.GetRookMovesMask(fromSquare, rookOccupancy)) & ~Occupancy & ToSquareMask, _ => throw new Exception($"{MoveGeneration} move generation not supported.") }; int toSquare; while ((toSquare = Bitwise.FindFirstSetBit(queenDestinations)) != Square.Illegal) { var victim = GetPiece(toSquare); var move = Move.Null; Move.SetFrom(ref move, fromSquare); Move.SetTo(ref move, toSquare); if (victim != Piece.None) { Move.SetCaptureAttacker(ref move, attacker); } Move.SetCaptureVictim(ref move, victim); Move.SetIsQuiet(ref move, victim == Piece.None); Moves[MoveIndex] = move; MoveIndex++; Bitwise.ClearBit(ref queenDestinations, toSquare); } Bitwise.ClearBit(ref queens, fromSquare); } }
private void GenerateKnightMoves(MoveGeneration MoveGeneration, ulong FromSquareMask, ulong ToSquareMask) { ulong knights; ulong unOrEnemyOccupiedSquares; ulong enemyOccupiedSquares; int attacker; if (WhiteMove) { // White Move knights = WhiteKnights & FromSquareMask; unOrEnemyOccupiedSquares = ~OccupancyWhite; enemyOccupiedSquares = OccupancyBlack; attacker = Piece.WhiteKnight; } else { // Black Move knights = BlackKnights & FromSquareMask; unOrEnemyOccupiedSquares = ~OccupancyBlack; enemyOccupiedSquares = OccupancyWhite; attacker = Piece.BlackKnight; } int fromSquare; while ((fromSquare = Bitwise.FindFirstSetBit(knights)) != Square.Illegal) { var knightDestinations = MoveGeneration switch { MoveGeneration.AllMoves => Board.KnightMoveMasks[fromSquare] & unOrEnemyOccupiedSquares & ToSquareMask, MoveGeneration.OnlyCaptures => Board.KnightMoveMasks[fromSquare] & enemyOccupiedSquares & ToSquareMask, MoveGeneration.OnlyNonCaptures => Board.KnightMoveMasks[fromSquare] & ~Occupancy & ToSquareMask, _ => throw new Exception($"{MoveGeneration} move generation not supported.") }; int toSquare; while ((toSquare = Bitwise.FindFirstSetBit(knightDestinations)) != Square.Illegal) { var victim = GetPiece(toSquare); var move = Move.Null; Move.SetFrom(ref move, fromSquare); Move.SetTo(ref move, toSquare); if (victim != Piece.None) { Move.SetCaptureAttacker(ref move, attacker); } Move.SetCaptureVictim(ref move, victim); Move.SetIsQuiet(ref move, victim == Piece.None); Moves[MoveIndex] = move; MoveIndex++; Bitwise.ClearBit(ref knightDestinations, toSquare); } Bitwise.ClearBit(ref knights, fromSquare); } }
public void FindPinnedPieces() { int ownKingSquare; ulong ownPieces; ulong enemyRankFileAttackers; ulong enemyDiagonalAttackers; ulong enemyPieces; if (WhiteMove) { // White Move ownKingSquare = Bitwise.FindFirstSetBit(WhiteKing); ownPieces = OccupancyWhite; enemyRankFileAttackers = BlackRooks | BlackQueens; enemyDiagonalAttackers = BlackBishops | BlackQueens; enemyPieces = OccupancyBlack; } else { // Black Move ownKingSquare = Bitwise.FindFirstSetBit(BlackKing); ownPieces = OccupancyBlack; enemyRankFileAttackers = WhiteRooks | WhiteQueens; enemyDiagonalAttackers = WhiteBishops | WhiteQueens; enemyPieces = OccupancyWhite; } // Find pieces pinned to own king by enemy rank / file attackers. PinnedPieces = 0; int attackerSquare; while ((attackerSquare = Bitwise.FindFirstSetBit(enemyRankFileAttackers)) != Square.Illegal) { var betweenSquares = Board.RankFileBetweenSquares[attackerSquare][ownKingSquare]; if (betweenSquares == 0) { Bitwise.ClearBit(ref enemyRankFileAttackers, attackerSquare); continue; } if ((betweenSquares & enemyPieces) == 0) { // No enemy pieces between enemy attacker and own king. var potentiallyPinnedPieces = betweenSquares & ownPieces; if (Bitwise.CountSetBits(potentiallyPinnedPieces) == 1) { // Exactly one own piece between enemy attacker and own king. // Piece is pinned to own king. PinnedPieces |= potentiallyPinnedPieces; } } Bitwise.ClearBit(ref enemyRankFileAttackers, attackerSquare); } // Find pieces pinned to own king by enemy diagonal attackers. while ((attackerSquare = Bitwise.FindFirstSetBit(enemyDiagonalAttackers)) != Square.Illegal) { var betweenSquares = Board.DiagonalBetweenSquares[attackerSquare][ownKingSquare]; if (betweenSquares == 0) { Bitwise.ClearBit(ref enemyDiagonalAttackers, attackerSquare); continue; } if ((betweenSquares & enemyPieces) == 0) { // No enemy pieces between enemy attacker and own king. var potentiallyPinnedPieces = betweenSquares & ownPieces; if (Bitwise.CountSetBits(potentiallyPinnedPieces) == 1) { // Exactly one own piece between enemy attacker and own king. // Piece is pinned to own king. PinnedPieces |= potentiallyPinnedPieces; } } Bitwise.ClearBit(ref enemyDiagonalAttackers, attackerSquare); } }
private void GenerateKingMoves(MoveGeneration MoveGeneration, ulong FromSquareMask, ulong ToSquareMask) { ulong king; ulong unOrEnemyOccupiedSquares; ulong enemyOccupiedSquares; int attacker; bool castleQueenside; ulong castleQueensideMask; bool castleKingside; ulong castleKingsideMask; if (WhiteMove) { // White Move king = WhiteKing & FromSquareMask; unOrEnemyOccupiedSquares = ~OccupancyWhite; enemyOccupiedSquares = OccupancyBlack; attacker = Piece.WhiteKing; castleQueenside = Engine.Castling.WhiteQueenside(Castling); castleQueensideMask = Board.WhiteCastleQEmptySquaresMask; castleKingside = Engine.Castling.WhiteKingside(Castling); castleKingsideMask = Board.WhiteCastleKEmptySquaresMask; } else { // Black Move king = BlackKing & FromSquareMask; unOrEnemyOccupiedSquares = ~OccupancyBlack; enemyOccupiedSquares = OccupancyWhite; attacker = Piece.BlackKing; castleQueenside = Engine.Castling.BlackQueenside(Castling); castleQueensideMask = Board.BlackCastleQEmptySquaresMask; castleKingside = Engine.Castling.BlackKingside(Castling); castleKingsideMask = Board.BlackCastleKEmptySquaresMask; } ulong move; var fromSquare = Bitwise.FindFirstSetBit(king); if (fromSquare == Square.Illegal) { return; } var kingDestinations = MoveGeneration switch { MoveGeneration.AllMoves => Board.KingMoveMasks[fromSquare] & unOrEnemyOccupiedSquares & ToSquareMask, MoveGeneration.OnlyCaptures => Board.KingMoveMasks[fromSquare] & enemyOccupiedSquares & ToSquareMask, MoveGeneration.OnlyNonCaptures => Board.KingMoveMasks[fromSquare] & ~Occupancy & ToSquareMask, _ => throw new Exception($"{MoveGeneration} move generation not supported.") }; int toSquare; while ((toSquare = Bitwise.FindFirstSetBit(kingDestinations)) != Square.Illegal) { var victim = GetPiece(toSquare); move = Move.Null; Move.SetFrom(ref move, fromSquare); Move.SetTo(ref move, toSquare); if (victim != Piece.None) { Move.SetCaptureAttacker(ref move, attacker); } Move.SetCaptureVictim(ref move, victim); Move.SetIsKingMove(ref move, true); Move.SetIsQuiet(ref move, victim == Piece.None); Moves[MoveIndex] = move; MoveIndex++; Bitwise.ClearBit(ref kingDestinations, toSquare); } if (MoveGeneration != MoveGeneration.OnlyCaptures) { if (castleQueenside && ((Occupancy & castleQueensideMask) == 0)) { // Castle Queenside if (WhiteMove) { // White Move fromSquare = Square.e1; toSquare = Square.c1; } else { // Black Move fromSquare = Square.e8; toSquare = Square.c8; } if ((Board.SquareMasks[toSquare] & ToSquareMask) > 0) { move = Move.Null; Move.SetFrom(ref move, fromSquare); Move.SetTo(ref move, toSquare); Move.SetIsCastling(ref move, true); Move.SetIsKingMove(ref move, true); Move.SetIsQuiet(ref move, false); Moves[MoveIndex] = move; MoveIndex++; } } if (castleKingside && ((Occupancy & castleKingsideMask) == 0)) { // Castle Kingside if (WhiteMove) { // White Move fromSquare = Square.e1; toSquare = Square.g1; } else { // Black Move fromSquare = Square.e8; toSquare = Square.g8; } if ((Board.SquareMasks[toSquare] & ToSquareMask) > 0) { move = Move.Null; Move.SetFrom(ref move, fromSquare); Move.SetTo(ref move, toSquare); Move.SetIsCastling(ref move, true); Move.SetIsKingMove(ref move, true); Move.SetIsQuiet(ref move, false); Moves[MoveIndex] = move; MoveIndex++; } } } }
private void GeneratePawnMoves(MoveGeneration MoveGeneration, ulong FromSquareMask, ulong ToSquareMask) { ulong pawns; ulong[] pawnMoveMasks; ulong[] pawnDoubleMoveMasks; ulong[] pawnAttackMasks; ulong enemyOccupiedSquares; var unoccupiedSquares = ~Occupancy; int[] ranks; int attacker; int queen; int rook; int bishop; int knight; int enPassantVictim; if (WhiteMove) { // White Move pawns = WhitePawns & FromSquareMask; pawnMoveMasks = Board.WhitePawnMoveMasks; pawnDoubleMoveMasks = Board.WhitePawnDoubleMoveMasks; pawnAttackMasks = Board.WhitePawnAttackMasks; enemyOccupiedSquares = OccupancyBlack; ranks = Board.WhiteRanks; attacker = Piece.WhitePawn; queen = Piece.WhiteQueen; rook = Piece.WhiteRook; bishop = Piece.WhiteBishop; knight = Piece.WhiteKnight; enPassantVictim = Piece.BlackPawn; } else { // Black Move pawns = BlackPawns & FromSquareMask; pawnMoveMasks = Board.BlackPawnMoveMasks; pawnDoubleMoveMasks = Board.BlackPawnDoubleMoveMasks; pawnAttackMasks = Board.BlackPawnAttackMasks; enemyOccupiedSquares = OccupancyWhite; ranks = Board.BlackRanks; attacker = Piece.BlackPawn; queen = Piece.BlackQueen; rook = Piece.BlackRook; bishop = Piece.BlackBishop; knight = Piece.BlackKnight; enPassantVictim = Piece.WhitePawn; } int fromSquare; ulong move; if ((EnPassantSquare != Square.Illegal) && ((Board.SquareMasks[EnPassantSquare] & ToSquareMask) > 0) && (MoveGeneration != MoveGeneration.OnlyNonCaptures)) { var enPassantAttackers = Board.EnPassantAttackerMasks[EnPassantSquare] & pawns; while ((fromSquare = Bitwise.FindFirstSetBit(enPassantAttackers)) != Square.Illegal) { // Capture pawn en passant. move = Move.Null; Move.SetFrom(ref move, fromSquare); Move.SetTo(ref move, EnPassantSquare); Move.SetCaptureAttacker(ref move, attacker); Move.SetCaptureVictim(ref move, enPassantVictim); Move.SetIsEnPassantCapture(ref move, true); Move.SetIsPawnMove(ref move, true); Move.SetIsQuiet(ref move, false); Moves[MoveIndex] = move; MoveIndex++; Bitwise.ClearBit(ref enPassantAttackers, fromSquare); } } while ((fromSquare = Bitwise.FindFirstSetBit(pawns)) != Square.Illegal) { ulong pawnDestinations; int toSquare; int toSquareRank; if (MoveGeneration != MoveGeneration.OnlyCaptures) { // Pawns may move forward one square (or two if on initial square) if forward squares are unoccupied. pawnDestinations = pawnMoveMasks[fromSquare] & unoccupiedSquares & ToSquareMask; while ((toSquare = Bitwise.FindFirstSetBit(pawnDestinations)) != Square.Illegal) { var doubleMove = Board.SquareDistances[fromSquare][toSquare] == 2; if (doubleMove && ((Occupancy & pawnDoubleMoveMasks[fromSquare]) > 0)) { // Double move is blocked. Bitwise.ClearBit(ref pawnDestinations, toSquare); continue; } toSquareRank = ranks[toSquare]; if (toSquareRank < 7) { move = Move.Null; Move.SetFrom(ref move, fromSquare); Move.SetTo(ref move, toSquare); Move.SetIsDoublePawnMove(ref move, doubleMove); Move.SetIsPawnMove(ref move, true); Move.SetIsQuiet(ref move, true); Moves[MoveIndex] = move; MoveIndex++; } else { // Promote pawn to queen. move = Move.Null; Move.SetFrom(ref move, fromSquare); Move.SetTo(ref move, toSquare); Move.SetPromotedPiece(ref move, queen); Move.SetIsPawnMove(ref move, true); Move.SetIsQuiet(ref move, false); Moves[MoveIndex] = move; MoveIndex++; // Promote pawn to rook. move = Move.Null; Move.SetFrom(ref move, fromSquare); Move.SetTo(ref move, toSquare); Move.SetPromotedPiece(ref move, rook); Move.SetIsPawnMove(ref move, true); Move.SetIsQuiet(ref move, false); Moves[MoveIndex] = move; MoveIndex++; // Promote pawn to bishop. move = Move.Null; Move.SetFrom(ref move, fromSquare); Move.SetTo(ref move, toSquare); Move.SetPromotedPiece(ref move, bishop); Move.SetIsPawnMove(ref move, true); Move.SetIsQuiet(ref move, false); Moves[MoveIndex] = move; MoveIndex++; // Promote pawn to knight. move = Move.Null; Move.SetFrom(ref move, fromSquare); Move.SetTo(ref move, toSquare); Move.SetPromotedPiece(ref move, knight); Move.SetIsPawnMove(ref move, true); Move.SetIsQuiet(ref move, false); Moves[MoveIndex] = move; MoveIndex++; } Bitwise.ClearBit(ref pawnDestinations, toSquare); } } if (MoveGeneration != MoveGeneration.OnlyNonCaptures) { // Pawns may attack diagonally forward one square if occupied by enemy. pawnDestinations = pawnAttackMasks[fromSquare] & enemyOccupiedSquares & ToSquareMask; while ((toSquare = Bitwise.FindFirstSetBit(pawnDestinations)) != Square.Illegal) { toSquareRank = ranks[toSquare]; var victim = GetPiece(toSquare); if (toSquareRank < 7) { move = Move.Null; Move.SetFrom(ref move, fromSquare); Move.SetTo(ref move, toSquare); Move.SetCaptureAttacker(ref move, attacker); Move.SetCaptureVictim(ref move, victim); Move.SetIsPawnMove(ref move, true); Move.SetIsQuiet(ref move, false); Moves[MoveIndex] = move; MoveIndex++; } else { // Promote pawn to queen. move = Move.Null; Move.SetFrom(ref move, fromSquare); Move.SetTo(ref move, toSquare); Move.SetPromotedPiece(ref move, queen); Move.SetCaptureAttacker(ref move, attacker); Move.SetCaptureVictim(ref move, victim); Move.SetIsPawnMove(ref move, true); Move.SetIsQuiet(ref move, false); Moves[MoveIndex] = move; MoveIndex++; // Promote pawn to rook. move = Move.Null; Move.SetFrom(ref move, fromSquare); Move.SetTo(ref move, toSquare); Move.SetPromotedPiece(ref move, rook); Move.SetCaptureAttacker(ref move, attacker); Move.SetCaptureVictim(ref move, victim); Move.SetIsPawnMove(ref move, true); Move.SetIsQuiet(ref move, false); Moves[MoveIndex] = move; MoveIndex++; // Promote pawn to bishop. move = Move.Null; Move.SetFrom(ref move, fromSquare); Move.SetTo(ref move, toSquare); Move.SetPromotedPiece(ref move, bishop); Move.SetCaptureAttacker(ref move, attacker); Move.SetCaptureVictim(ref move, victim); Move.SetIsPawnMove(ref move, true); Move.SetIsQuiet(ref move, false); Moves[MoveIndex] = move; MoveIndex++; // Promote pawn to knight. move = Move.Null; Move.SetFrom(ref move, fromSquare); Move.SetTo(ref move, toSquare); Move.SetPromotedPiece(ref move, knight); Move.SetCaptureAttacker(ref move, attacker); Move.SetCaptureVictim(ref move, victim); Move.SetIsPawnMove(ref move, true); Move.SetIsQuiet(ref move, false); Moves[MoveIndex] = move; MoveIndex++; } Bitwise.ClearBit(ref pawnDestinations, toSquare); } } Bitwise.ClearBit(ref pawns, fromSquare); } }