예제 #1
0
        internal void SetGameState()
        {
            Player opponent      = WhoseTurn;
            Player lastPlayer    = ChessUtilities.RevertPlayer(opponent);
            bool   isInCheck     = ChessUtilities.IsPlayerInCheck(opponent, this);
            var    hasValidMoves = ChessUtilities.GetValidMoves(this).Count > 0;

            if (isInCheck && !hasValidMoves)
            {
                GameState = lastPlayer == Player.White ? GameState.WhiteWinner : GameState.BlackWinner;
                return;
            }

            if (!hasValidMoves)
            {
                GameState = GameState.Stalemate;
                return;
            }

            if (isInCheck)
            {
                GameState = opponent == Player.White ? GameState.WhiteInCheck : GameState.BlackInCheck;
                return;
            }
            GameState = IsInsufficientMaterial() ? GameState.Draw : GameState.NotCompleted;
        }
예제 #2
0
        internal bool PlayerWillBeInCheck(Move move)
        {
            if (move == null)
            {
                throw new ArgumentNullException(nameof(move));
            }

            ChessGame clone = DeepClone(); // Make the move on this board to keep original board as is.
            Piece     piece = clone[move.Source];

            clone.Board[(int)move.Source.Rank, (int)move.Source.File]           = null;
            clone.Board[(int)move.Destination.Rank, (int)move.Destination.File] = piece;

            return(ChessUtilities.IsPlayerInCheck(move.Player, clone));
        }
예제 #3
0
        internal bool PlayerWillBeInCheck(Move move)
        {
            if (move == null)
            {
                throw new ArgumentNullException(nameof(move));
            }

            ChessGame clone = DeepClone();                               // Make the move on this board to keep original board as is.
            Piece?    piece = clone[move.Source.File, move.Source.Rank]; // TODO: throwing causes un-intended behavior. ?? throw new ArgumentException("Invalid move", nameof(move));

            clone.Board[(int)move.Source.Rank][(int)move.Source.File]           = null;
            clone.Board[(int)move.Destination.Rank][(int)move.Destination.File] = piece;

            return(ChessUtilities.IsPlayerInCheck(move.Player, clone));
        }
예제 #4
0
        /// <summary>Makes a move in the game.</summary>
        /// <param name="move">The <see cref="Move"/> you want to make.</param>
        /// <param name="isMoveValidated">Only pass true when you've already checked that the move is valid.</param>
        /// <returns>Returns true if the move is made; false otherwise.</returns>
        /// <exception cref="ArgumentNullException">
        ///     The <c>move</c> is null.
        /// </exception>
        /// <exception cref="InvalidOperationException">
        ///     The <see cref="Move.Source"/> square of the <c>move</c> doesn't contain a piece.
        /// </exception>
        /// <exception cref="ArgumentNullException">
        ///    The <c>move.PromoteTo</c> is null and the move is a pawn promotion move.
        /// </exception>
        public bool MakeMove(Move move, bool isMoveValidated)
        {
            if (move == null)
            {
                throw new ArgumentNullException(nameof(move));
            }

            Piece piece = this[move.Source];

            if (piece == null)
            {
                throw new InvalidOperationException("Source square has no piece.");
            }

            if (!isMoveValidated && !IsValidMove(move))
            {
                return(false);
            }

            SetCastleStatus(move, piece);

            if (piece is King && move.GetAbsDeltaX() == 2)
            {
                // Queen-side castle
                if (move.Destination.File == File.C)
                {
                    var rook = this[File.A, move.Source.Rank];
                    Board[(int)move.Source.Rank, (int)File.A] = null;
                    Board[(int)move.Source.Rank, (int)File.D] = rook;
                }

                // King-side castle
                if (move.Destination.File == File.G)
                {
                    var rook = this[File.H, move.Source.Rank];
                    Board[(int)move.Source.Rank, (int)File.H] = null;
                    Board[(int)move.Source.Rank, (int)File.F] = rook;
                }
            }

            if (piece is Pawn)
            {
                if ((move.Player == Player.White && move.Destination.Rank == Rank.Eighth) ||
                    (move.Player == Player.Black && move.Destination.Rank == Rank.First))
                {
                    switch (move.PromoteTo)
                    {
                    case PawnPromotion.Knight:
                        piece = new Knight(piece.Owner);
                        break;

                    case PawnPromotion.Bishop:
                        piece = new Bishop(piece.Owner);
                        break;

                    case PawnPromotion.Rook:
                        piece = new Rook(piece.Owner);
                        break;

                    case PawnPromotion.Queen:
                        piece = new Queen(piece.Owner);
                        break;

                    default:
                        throw new ArgumentNullException(nameof(move.PromoteTo));
                    }
                }
                // Enpassant
                if (Pawn.GetPawnMoveType(move) == PawnMoveType.Capture &&
                    this[move.Destination] == null)
                {
                    Board[(int)Moves.Last().Destination.Rank, (int)Moves.Last().Destination.File] = null;
                }
            }
            Board[(int)move.Source.Rank, (int)move.Source.File]           = null;
            Board[(int)move.Destination.Rank, (int)move.Destination.File] = piece;
            Moves.Add(move);
            WhoseTurn = ChessUtilities.RevertPlayer(move.Player);
            SetGameState();
            return(true);
        }