private void AddBishopAttack(SortedDictionary <int, SquareFlag> dictionary, int squareIndex, SquareFlag currentOccupancy) { var magicIndex = MagicIndexHelpers.GetBishopMagicIndex(squareIndex, currentOccupancy); var attack = AttackGenerator.GeneratePotentialBishopAttacks(squareIndex, currentOccupancy); var indexTaken = dictionary.ContainsKey(magicIndex) && dictionary[magicIndex] != attack; if (indexTaken) { throw new Exception($"Magic Index {magicIndex} already in use by a different attack"); } dictionary[magicIndex] = attack; }
private SquareFlag GetAttackableSquares(Square fromSquare, PieceType rayType, SquareFlag occupiedSquares) { var occupancyMask = rayType == PieceType.Rook ? MagicNumbers.RookOccupancyMasks[fromSquare.Index] : MagicNumbers.BishopOccupancyMasks[fromSquare.Index]; var occupancyMasked = occupiedSquares & occupancyMask; var magicIndex = MagicIndexHelpers.GetMagicIndex(rayType, fromSquare.Index, occupancyMasked); var attackableSquaresIncludingSelfCaptures = rayType == PieceType.Rook ? AttackBitmaps.RookAttacks[fromSquare.Index][magicIndex] : AttackBitmaps.BishopAttacks[fromSquare.Index][magicIndex]; return(attackableSquaresIncludingSelfCaptures); }
private void AddIndividualPawnCaptures(MoveGenerationWorkspace workspace, Square fromSquare, SquareFlag pushMask, SquareFlag captureMask) { var relativeBitBoard = workspace.RelativeBitBoard; var captureSquares = relativeBitBoard.Colour == Colour.White ? AttackBitmaps.PawnCapturesWhite[fromSquare.Index].ToList() : AttackBitmaps.PawnCapturesBlack[fromSquare.Index].ToList(); foreach (var toSquare in captureSquares) { var moveType = relativeBitBoard.EnPassant.HasFlag(toSquare) ? MoveType.EnPassant : MoveType.Ordinary; if (relativeBitBoard.OpponentSquares.HasFlag(toSquare) || moveType == MoveType.EnPassant) { var capturePieceType = relativeBitBoard.GetPieceType(toSquare); var discoveredCheck = false; if (moveType != MoveType.EnPassant) { if (!captureMask.HasFlag(toSquare)) { continue; } } else { // Abuse the push system - push an imaginary pawn from the en passant square as opponent to find piece var enPassantCaptureSquare = relativeBitBoard.EnPassant.PawnForward(relativeBitBoard.OpponentColour, 1); var blockWithPush = pushMask.HasFlag(relativeBitBoard.EnPassant); var evadeWithCapture = captureMask.HasFlag(enPassantCaptureSquare); if (!blockWithPush && !evadeWithCapture) { continue; } capturePieceType = PieceType.Pawn; // Looking for DISCOVERED CHECK (not spotted by pinned pieces as there are 2 pawns in the way) // Slight duplication here but probably cleaner than passing in var kingSquare = relativeBitBoard.MyKing.ToSquare(); var enPassantDiscoveredCheckRank = relativeBitBoard.EnPassantDiscoveredCheckRank; // This should be super rare. Performing an en passant capture with our King on same rank. if (enPassantDiscoveredCheckRank.HasFlag(kingSquare.Flag)) { if ((enPassantDiscoveredCheckRank & relativeBitBoard.OpponentRooks) > 0 || (enPassantDiscoveredCheckRank & relativeBitBoard.OpponentQueens) > 0) { var occupancyMask = MagicNumbers.RookOccupancyMasks[kingSquare.Index]; var occupancyBeforeCapture = relativeBitBoard.OccupiedSquares & occupancyMask; var occupancyAfterCapture = occupancyBeforeCapture & ~enPassantCaptureSquare & ~fromSquare.Flag; // Search for magic moves using just the occupancy of rank (the rest is not relevant) var magicIndex = MagicIndexHelpers.GetMagicIndex(PieceType.Rook, kingSquare.Index, occupancyAfterCapture); var kingRayAttacks = AttackBitmaps.RookAttacks[kingSquare.Index][magicIndex]; var kingRayAttacksOnRank = kingRayAttacks & enPassantDiscoveredCheckRank; discoveredCheck = (kingRayAttacksOnRank & relativeBitBoard.OpponentRooks) > 0 || (kingRayAttacksOnRank & relativeBitBoard.OpponentQueens) > 0; } } } if (relativeBitBoard.PromotionRank.HasFlag(toSquare)) { AddPromotions(workspace, fromSquare, toSquare.ToSquare(), capturePieceType); } else if (!discoveredCheck) { if (capturePieceType != PieceType.None) { workspace.CaptureMoveBuffer.Add(MoveBuilder.Create(workspace.Colour, PieceType.Pawn, fromSquare, toSquare.ToSquare(), capturePieceType, moveType, workspace.NumCheckers)); } else { workspace.NonCaptureMoveBuffer.Add(MoveBuilder.Create(workspace.Colour, PieceType.Pawn, fromSquare, toSquare.ToSquare(), capturePieceType, moveType, workspace.NumCheckers)); } } } } }