private void AddPawnMoves(IList <Move> moves, bool onlyCaptures) { var pawnDirection = board.Us == Piece.WHITE ? Directions[N] : Directions[S]; var promotionRank = board.Us == Piece.WHITE ? 7 : 0; //one square moves var ourPawnsBitboard = board.Us == Piece.WHITE ? board.WhitePawnBitboard : board.BlackPawnBitboard; var pinnedPawns = pinBitmask & ourPawnsBitboard; if (!onlyCaptures) { var pseudoLegalSinglePawnMoveTargets = board.Us == Piece.WHITE ? BitboardUtilities.ShiftUp(ourPawnsBitboard) : BitboardUtilities.ShiftDown(ourPawnsBitboard); pseudoLegalSinglePawnMoveTargets &= freeSquares; var legalSinglePawnMoveTarget = pseudoLegalSinglePawnMoveTargets & rayCheckBitmask; while (legalSinglePawnMoveTarget != 0) { var targetSquare = BitOperations.TrailingZeroCount(legalSinglePawnMoveTarget); var startSquare = targetSquare - pawnDirection; legalSinglePawnMoveTarget ^= 1ul << targetSquare; if ((pinnedPawns & (1ul << startSquare)) != 0 && !IsMovingAlongRay(pawnDirection, startSquare, ourKingSquare)) { continue; } if (targetSquare / 8 == promotionRank) { moves.Add(new Move(startSquare, targetSquare, board).PromoteTo(Piece.QUEEN)); moves.Add(new Move(startSquare, targetSquare, board).PromoteTo(Piece.ROOK)); moves.Add(new Move(startSquare, targetSquare, board).PromoteTo(Piece.BISHOP)); moves.Add(new Move(startSquare, targetSquare, board).PromoteTo(Piece.KNIGHT)); } else { moves.Add(new Move(startSquare, targetSquare, board)); } } var doublePawnMoveTarget = board.Us == Piece.WHITE ? BitboardUtilities.ShiftUp(pseudoLegalSinglePawnMoveTargets) : BitboardUtilities.ShiftDown(pseudoLegalSinglePawnMoveTargets); doublePawnMoveTarget &= RankBitboards[board.Us == Piece.WHITE ? 3 : 4] & freeSquares & rayCheckBitmask; while (doublePawnMoveTarget != 0) { var targetSquare = BitOperations.TrailingZeroCount(doublePawnMoveTarget); var startSquare = targetSquare - 2 * pawnDirection; doublePawnMoveTarget ^= 1ul << targetSquare; if ((pinnedPawns & (1ul << startSquare)) != 0) { if (!IsMovingAlongRay(pawnDirection, startSquare, ourKingSquare)) { continue; } } moves.Add(new Move(startSquare, targetSquare, board).DoublePawnMove()); } } //Captures var upWest = Directions[board.Us == Piece.WHITE ? NW : SW]; var upEast = Directions[board.Us == Piece.WHITE ? NE : SE]; var enemyPiecesAndEnPassent = board.EnPassentSquare >= 0 ? enemyPieces | (1ul << board.EnPassentSquare) : enemyPieces; var captureUpWestTargets = board.Us == Piece.WHITE ? BitboardUtilities.ShiftUpLeft(ourPawnsBitboard) : BitboardUtilities.ShiftDownLeft(ourPawnsBitboard); captureUpWestTargets &= enemyPiecesAndEnPassent & rayCheckBitmask; var captureUpEastTargets = board.Us == Piece.WHITE ? BitboardUtilities.ShiftUpRight(ourPawnsBitboard) : BitboardUtilities.ShiftDownRight(ourPawnsBitboard); captureUpEastTargets &= enemyPiecesAndEnPassent & rayCheckBitmask; while (captureUpWestTargets != 0) { var targetSquare = BitOperations.TrailingZeroCount(captureUpWestTargets); var startSquare = targetSquare - upWest; captureUpWestTargets ^= 1ul << targetSquare; if ((pinnedPawns & (1ul << startSquare)) != 0 && !IsMovingAlongRay(upWest, startSquare, ourKingSquare)) { continue; } if (targetSquare / 8 == promotionRank) { moves.Add(new Move(startSquare, targetSquare, board).PromoteTo(Piece.QUEEN)); moves.Add(new Move(startSquare, targetSquare, board).PromoteTo(Piece.ROOK)); moves.Add(new Move(startSquare, targetSquare, board).PromoteTo(Piece.BISHOP)); moves.Add(new Move(startSquare, targetSquare, board).PromoteTo(Piece.KNIGHT)); } else { var move = new Move(startSquare, targetSquare, board); if (targetSquare == board.EnPassentSquare) { move.EnPassent(); } moves.Add(move); } } while (captureUpEastTargets != 0) { var targetSquare = BitOperations.TrailingZeroCount(captureUpEastTargets); var startSquare = targetSquare - upEast; captureUpEastTargets ^= 1ul << targetSquare; if ((pinnedPawns & (1ul << startSquare)) != 0 && !IsMovingAlongRay(upEast, startSquare, ourKingSquare)) { continue; } if (targetSquare / 8 == promotionRank) { moves.Add(new Move(startSquare, targetSquare, board).PromoteTo(Piece.QUEEN)); moves.Add(new Move(startSquare, targetSquare, board).PromoteTo(Piece.ROOK)); moves.Add(new Move(startSquare, targetSquare, board).PromoteTo(Piece.BISHOP)); moves.Add(new Move(startSquare, targetSquare, board).PromoteTo(Piece.KNIGHT)); } else { var move = new Move(startSquare, targetSquare, board); if (targetSquare == board.EnPassentSquare) { move.EnPassent(); } moves.Add(move); } } }