public static long GetEnPassantHash([CanBeNull] EnPassantCaptureInfo info, Bitboard activeSidePawns) { if (info is null) { return(0); } var targetPieceSquare = info.TargetPieceSquare; var adjacentPawnsBitboard = EnPassantAdjacentPawnsBitboardMap[targetPieceSquare]; if ((adjacentPawnsBitboard & activeSidePawns).IsNone) { return(0); } var file = targetPieceSquare.File; var result = (long)Randoms[RandomsEnPassantOffset + file]; return(result); }
protected static void AssertBaseProperties( [NotNull] GameBoard gameBoard, GameSide expectedActiveSide, CastlingOptions expectedCastlingOptions, EnPassantCaptureInfo expectedEnPassantCaptureInfo, int expectedHalfMoveCountBy50MoveRule, int expectedFullMoveIndex, GameState expectedGameState, AutoDrawType autoDrawType = AutoDrawType.None) { Assert.That(gameBoard, Is.Not.Null); Assert.That(gameBoard.ActiveSide, Is.EqualTo(expectedActiveSide)); Assert.That(gameBoard.CastlingOptions, Is.EqualTo(expectedCastlingOptions)); AssertEnPassantCaptureInfo(gameBoard.EnPassantCaptureInfo, expectedEnPassantCaptureInfo); Assert.That(gameBoard.FullMoveIndex, Is.EqualTo(expectedFullMoveIndex)); Assert.That(gameBoard.HalfMoveCountBy50MoveRule, Is.EqualTo(expectedHalfMoveCountBy50MoveRule)); Assert.That(gameBoard.FullMoveCountBy50MoveRule, Is.EqualTo(expectedHalfMoveCountBy50MoveRule / 2)); Assert.That(gameBoard.State, Is.EqualTo(expectedGameState)); Assert.That(gameBoard.GetAutoDrawType(), Is.EqualTo(autoDrawType)); }
public bool IsEnPassantCapture( Square source, Square destination, EnPassantCaptureInfo enPassantCaptureInfo) { if (enPassantCaptureInfo is null || enPassantCaptureInfo.CaptureSquare != destination) { return(false); } var piece = PiecePosition[source]; if (piece.GetPieceType() != PieceType.Pawn) { return(false); } var targetPiece = PiecePosition[enPassantCaptureInfo.TargetPieceSquare]; return(targetPiece.GetPieceType() == PieceType.Pawn); }
private static void AssertEnPassantCaptureInfo( EnPassantCaptureInfo actualEnPassantCaptureInfo, EnPassantCaptureInfo expectedEnPassantCaptureInfo) { if (expectedEnPassantCaptureInfo is null) { Assert.That(actualEnPassantCaptureInfo, Is.Null); return; } Assert.That(actualEnPassantCaptureInfo, Is.Not.Null); Assert.That( actualEnPassantCaptureInfo.CaptureSquare, Is.EqualTo(expectedEnPassantCaptureInfo.CaptureSquare), "Capture Square."); Assert.That( actualEnPassantCaptureInfo.TargetPieceSquare, Is.EqualTo(expectedEnPassantCaptureInfo.TargetPieceSquare), "Target piece Square."); }
public static string GetFenSnippet(this EnPassantCaptureInfo enPassantCaptureInfo) { return(enPassantCaptureInfo?.CaptureSquare.ToString() ?? ChessConstants.NoEnPassantCaptureFenSnippet); }
internal MakeMoveData MakeMove( [NotNull] GameMove move, GameSide movingSide, [CanBeNull] EnPassantCaptureInfo enPassantCaptureInfo, ref CastlingOptions castlingOptions) { if (move is null) { throw new ArgumentNullException(nameof(move)); } var piece = PiecePosition[move.From]; if (piece == Piece.None || piece.GetSide() != movingSide) { throw new ArgumentException($@"Invalid move '{move}' in the position.", nameof(move)); } GameMove castlingRookMove = null; Square? enPassantCapturedPieceSquare = null; var movingSideAllCastlingOptions = ChessHelper.GameSideToCastlingOptionsMap[movingSide]; // Performing checks before actual move! var castlingInfo = CheckCastlingMove(move); var isEnPassantCapture = IsEnPassantCapture(move.From, move.To, enPassantCaptureInfo); var isPawnPromotion = IsPawnPromotion(move.From, move.To); var moveData = MovePieceInternal(move); var capturedPiece = moveData.CapturedPiece; if (isEnPassantCapture) { if (enPassantCaptureInfo is null) { throw ChessPlatformException.CreateInconsistentStateError(); } enPassantCapturedPieceSquare = enPassantCaptureInfo.TargetPieceSquare; capturedPiece = PiecePosition.SetPiece(enPassantCaptureInfo.TargetPieceSquare, Piece.None); if (capturedPiece.GetPieceType() != PieceType.Pawn) { throw ChessPlatformException.CreateInconsistentStateError(); } } else if (isPawnPromotion) { if (move.PromotionResult == PieceType.None) { throw new ChessPlatformException($@"Promoted piece type is not specified ({move})."); } var previousPiece = PiecePosition.SetPiece(move.To, move.PromotionResult.ToPiece(movingSide)); if (previousPiece.GetPieceType() != PieceType.Pawn) { throw ChessPlatformException.CreateInconsistentStateError(); } } else if (castlingInfo != null) { if (!castlingOptions.IsAllSet(castlingInfo.Option)) { throw new ChessPlatformException( $@"The castling {{{move}}} ({castlingInfo.CastlingType.GetName()}) is not allowed."); } castlingRookMove = castlingInfo.RookMove; var rookMoveData = MovePieceInternal(castlingRookMove); if (rookMoveData.CapturedPiece != Piece.None) { throw ChessPlatformException.CreateInconsistentStateError(); } castlingOptions &= ~movingSideAllCastlingOptions; } var movingSideCurrentCastlingOptions = castlingOptions & movingSideAllCastlingOptions; if (movingSideCurrentCastlingOptions != CastlingOptions.None) { switch (piece.GetPieceType()) { case PieceType.King: castlingOptions &= ~movingSideAllCastlingOptions; break; case PieceType.Rook: { var castlingInfoByRook = ChessConstants.AllCastlingInfos.SingleOrDefault(obj => obj.RookMove.From == move.From); if (castlingInfoByRook != null) { castlingOptions &= ~castlingInfoByRook.Option; } } break; } } var oppositeSide = movingSide.Invert(); var oppositeSideAllCastlingOptions = ChessHelper.GameSideToCastlingOptionsMap[oppositeSide]; var oppositeSideCurrentCastlingOptions = castlingOptions & oppositeSideAllCastlingOptions; if (oppositeSideCurrentCastlingOptions != CastlingOptions.None && capturedPiece.GetPieceType() == PieceType.Rook) { var oppositeCastlingInfo = ChessConstants.AllCastlingInfos.SingleOrDefault(obj => obj.RookMove.From == move.To); if (oppositeCastlingInfo != null) { castlingOptions &= ~oppositeCastlingInfo.Option; } } var undoMoveData = new MakeMoveData( move, moveData.MovedPiece, capturedPiece, castlingRookMove, enPassantCapturedPieceSquare); _undoMoveDatas.Push(undoMoveData); PiecePosition.EnsureConsistency(); return(undoMoveData); }
public Square[] GetPotentialMoveSquares( CastlingOptions castlingOptions, [CanBeNull] EnPassantCaptureInfo enPassantCaptureInfo, Square sourceSquare) { var piece = PiecePosition[sourceSquare]; var pieceType = piece.GetPieceType(); if (pieceType == PieceType.None) { throw new ArgumentException( $@"No piece at the source square '{sourceSquare}'.", nameof(sourceSquare)); } var pieceSide = piece.GetSide().EnsureNotNull(); switch (pieceType) { case PieceType.Knight: //// TODO [HarinezumiSama] Use bitboard instead of squares var result = ChessHelper.GetKnightMoveSquares(sourceSquare) .Where(square => PiecePosition[square].GetSide() != pieceSide) .ToArray(); return(result); case PieceType.King: case PieceType.Pawn: throw new InvalidOperationException("MUST NOT go into this branch anymore."); case PieceType.None: throw new ArgumentException( $@"No piece at the source square '{sourceSquare}'.", nameof(sourceSquare)); case PieceType.Bishop: case PieceType.Rook: case PieceType.Queen: // Just go ahead break; default: throw pieceType.CreateEnumValueNotImplementedException(); } var resultList = new List <Square>(); if (pieceType.IsSlidingStraight()) { GetPotentialMoveSquaresByRays( sourceSquare, pieceSide, ChessHelper.StraightRays, ChessHelper.MaxSlidingPieceDistance, true, resultList); } if (pieceType.IsSlidingDiagonally()) { GetPotentialMoveSquaresByRays( sourceSquare, pieceSide, ChessHelper.DiagonalRays, ChessHelper.MaxSlidingPieceDistance, true, resultList); } return(resultList.ToArray()); }