public void FindPinnedPieces() { var ownKingSquare = Bitwise.FirstSetSquare(GetKing(ColorToMove)); var ownPieces = ColorOccupancy[(int)ColorToMove]; var enemyRankFileAttackers = GetRooks(ColorLastMoved) | GetQueens(ColorLastMoved); var enemyDiagonalAttackers = GetBishops(ColorLastMoved) | GetQueens(ColorLastMoved); var enemyPieces = ColorOccupancy[(int)ColorLastMoved]; // Find pieces pinned to own king by enemy rank / file attackers. PinnedPieces = 0; Square attackerSquare; while ((attackerSquare = Bitwise.PopFirstSetSquare(ref enemyRankFileAttackers)) != Square.Illegal) { var betweenSquares = Board.RankFileBetweenSquares[(int)attackerSquare][(int)ownKingSquare]; if (betweenSquares == 0) { continue; } if ((betweenSquares & enemyPieces) == 0) { // No enemy pieces between enemy attacker and own king. var pinnedPieces = betweenSquares & ownPieces; if (Bitwise.CountSetBits(pinnedPieces) == 1) { // Exactly one own piece between enemy attacker and own king. // Piece is pinned to own king. PinnedPieces |= pinnedPieces; } } } // Find pieces pinned to own king by enemy diagonal attackers. while ((attackerSquare = Bitwise.PopFirstSetSquare(ref enemyDiagonalAttackers)) != Square.Illegal) { var betweenSquares = Board.DiagonalBetweenSquares[(int)attackerSquare][(int)ownKingSquare]; if (betweenSquares == 0) { continue; } if ((betweenSquares & enemyPieces) == 0) { // No enemy pieces between enemy attacker and own king. var pinnedPieces = betweenSquares & ownPieces; if (Bitwise.CountSetBits(pinnedPieces) == 1) { // Exactly one own piece between enemy attacker and own king. // Piece is pinned to own king. PinnedPieces |= pinnedPieces; } } } }
private void GenerateKingMoves(MoveGeneration moveGeneration, ulong fromSquareMask, ulong toSquareMask) { var king = GetKing(ColorToMove) & fromSquareMask; if (king == 0) { return; } var unOrEnemyOccupiedSquares = ~ColorOccupancy[(int)ColorToMove]; var enemyOccupiedSquares = ColorOccupancy[(int)ColorLastMoved]; var attacker = PieceHelper.GetPieceOfColor(ColorlessPiece.King, ColorToMove); ulong move; var fromSquare = Bitwise.FirstSetSquare(king); if (fromSquare == Square.Illegal) { return; } var kingDestinations = moveGeneration switch { MoveGeneration.AllMoves => Board.KingMoveMasks[(int)fromSquare] & unOrEnemyOccupiedSquares & toSquareMask, MoveGeneration.OnlyCaptures => Board.KingMoveMasks[(int)fromSquare] & enemyOccupiedSquares & toSquareMask, MoveGeneration.OnlyNonCaptures => Board.KingMoveMasks[(int)fromSquare] & ~Occupancy & toSquareMask, _ => throw new Exception($"{moveGeneration} move generation not supported.") }; Square toSquare; while ((toSquare = Bitwise.PopFirstSetSquare(ref kingDestinations)) != Square.Illegal) { var victim = GetPiece(toSquare); move = Move.Null; Move.SetPiece(ref move, attacker); 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); Moves[MoveIndex] = move; MoveIndex++; } if (moveGeneration != MoveGeneration.OnlyCaptures) { for (var boardSide = BoardSide.Queen; boardSide <= BoardSide.King; boardSide++) { var castleEmptySquaresMask = Board.CastleEmptySquaresMask[(int)ColorToMove][(int)boardSide]; if (!KingInCheck && Game.Castling.Permitted(Castling, ColorToMove, boardSide) && ((Occupancy & castleEmptySquaresMask) == 0)) { // Castle toSquare = Board.CastleToSquares[(int)ColorToMove][(int)boardSide]; if ((Board.SquareMasks[(int)toSquare] & toSquareMask) > 0) { move = Move.Null; Move.SetPiece(ref move, attacker); Move.SetFrom(ref move, fromSquare); Move.SetTo(ref move, toSquare); Move.SetIsCastling(ref move, true); Move.SetIsKingMove(ref move, true); Moves[MoveIndex] = move; MoveIndex++; } } } } }