Пример #1
0
        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));
        }
Пример #3
0
        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);
 }
Пример #6
0
        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);
        }
Пример #7
0
        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());
        }