public void MakeMove_GivenAValidTakingMove_RaisesPieceTakenEvent()
        {
            PieceTakenEventArgs pieceTakenEventArgs = null;
            var chessBoard = new ChessBoard();
            var blackKnight = new Knight(Colour.Black);
            var whitePawn = new Pawn(Colour.White);
            var boardPosition1 = new BoardPosition("A1");
            var boardPosition2 = new BoardPosition("B3");
            chessBoard.SetInitialPosition(boardPosition1, blackKnight);
            chessBoard.SetInitialPosition(boardPosition2, whitePawn);

            chessBoard.PieceTaken += (sender, e) =>
            {
                pieceTakenEventArgs = e;
            };

            chessBoard.MakeMove(boardPosition1, boardPosition2);

            Assert.That(pieceTakenEventArgs, Is.Not.Null);
            Assert.That(pieceTakenEventArgs.PieceTaken, Is.Not.Null);
            Assert.That(pieceTakenEventArgs.PieceTaken, Is.InstanceOf<Pawn>());
            Assert.That(pieceTakenEventArgs.PieceTaken.Colour, Is.EqualTo(Colour.White));
            Assert.That(pieceTakenEventArgs.Square, Is.Not.Null);
            Assert.That(pieceTakenEventArgs.Square.ChessPiece, Is.Not.Null);
            Assert.That(pieceTakenEventArgs.Square.ChessPiece, Is.InstanceOf<Knight>());
            Assert.That(pieceTakenEventArgs.Square.ChessPiece.Colour, Is.EqualTo(Colour.Black));
        }
Exemple #2
0
        internal override MoveResult ValidateMove(
            ChessBoard chessBoard,
            BoardPosition from,
            BoardPosition to,
            out ExceptionReasonDetail exceptionReasonDetail)
        {
            exceptionReasonDetail = ExceptionReasonDetail.None;
            MoveResult result = MoveResult.Illegal;

            int fileDiff = Math.Abs(from.InternalFile - to.InternalFile);
            int forward = (this.Colour == Colour.White) ? to.InternalRank - from.InternalRank : from.InternalRank - to.InternalRank;

            Square toSquare = chessBoard.GetSquare(to);

            if (forward == 1) {

                if (fileDiff == 0) {
                    if (toSquare.ChessPiece != null) {
                        result = MoveResult.Collision;
                    }
                    else {
                        result = MoveResult.Valid;
                    }
                }

                if (fileDiff == 1) {
                    if (toSquare.ChessPiece != null && toSquare.ChessPiece.Colour != this.Colour) {
                        result = MoveResult.Valid;
                    }
                    else {
                        exceptionReasonDetail = ExceptionReasonDetail.PawnCannotMoveDiagonallyUnlessCapturing;
                    }
                }
            }

            if (forward == 2 && fileDiff == 0) {
                bool onHomeRank = (this.Colour == Colour.White && from.Rank == 2) || (this.Colour == Colour.Black && from.Rank == 7);
                if (onHomeRank && chessBoard.Round == 1) {
                    int inbetweenFile = from.InternalFile;
                    int inbetweenRank = (this.Colour == Colour.White) ? from.InternalRank + 1 : from.InternalRank - 1;
                    Square inbetweenSquare = chessBoard.GetSquare(new BoardPosition(inbetweenFile, inbetweenRank));
                    if (inbetweenSquare.ChessPiece != null) {
                        result = MoveResult.Collision;
                    }
                    else {
                        if (toSquare.ChessPiece == null) {
                            result = MoveResult.Valid;
                        }
                    }
                }
                else {
                    exceptionReasonDetail = ExceptionReasonDetail.PawnCannotMoveTwoSpacesAtThisTime;
                }
            }

            return result;
        }
 /// <summary>
 /// Determine whether the given move is valid for this chess piece on the given chess board.
 /// </summary>
 /// <param name="chessBoard">The chess board on which the chess piece is being moved.</param>
 /// <param name="from">The board position from which the chess piece is being moved.</param>
 /// <param name="to">The board position to which the chess piece is being moved.</param>
 /// <returns></returns>
 internal virtual MoveResult ValidateMove(
     ChessBoard chessBoard,
     BoardPosition from,
     BoardPosition to,
     out ExceptionReasonDetail exceptionReasonDetail)
 {
     exceptionReasonDetail = ExceptionReasonDetail.None;
     return MoveResult.Illegal;
 }
        public void MakeMove_GivenAValidMove_Succeeds()
        {
            var chessBoard = new ChessBoard();
            var blackKnight = new Knight(Colour.Black);
            var boardPosition1 = new BoardPosition("A1");
            var boardPosition2 = new BoardPosition("B3");
            chessBoard.SetInitialPosition(boardPosition1, blackKnight);
            chessBoard.MakeMove(boardPosition1, boardPosition2);

            Assert.That(chessBoard.GetSquare(boardPosition1), Is.Not.Null);
            Assert.That(chessBoard.GetSquare(boardPosition1).ChessPiece, Is.Null);

            Assert.That(chessBoard.GetSquare(boardPosition2), Is.Not.Null);
            Assert.That(chessBoard.GetSquare(boardPosition2).ChessPiece, Is.Not.Null);
            Assert.That(chessBoard.GetSquare(boardPosition2).ChessPiece, Is.InstanceOf<Knight>());
            Assert.That(chessBoard.GetSquare(boardPosition2).ChessPiece.Colour, Is.EqualTo(Colour.Black));
        }
        public void MakeMove_GivenAnInvalidTakingMove_ThrowsException()
        {
            var chessBoard = new ChessBoard();
            var blackKnight = new Knight(Colour.Black);
            var blackPawn = new Pawn(Colour.Black);
            var boardPosition1 = new BoardPosition("A1");
            var boardPosition2 = new BoardPosition("B3");
            chessBoard.SetInitialPosition(boardPosition1, blackKnight);
            chessBoard.SetInitialPosition(boardPosition2, blackPawn);

            try {
                chessBoard.MakeMove(boardPosition1, boardPosition2);
                Assert.Fail("Expected a ChessBoardException to be thrown!");
            }
            catch (ChessBoardException ex) {
                Assert.That(ex.ExceptionReason, Is.EqualTo(ExceptionReason.IllegalMove));
            }
        }
        public void MakeMove_GivenAValidTakingMove_RaisesGameOverEvent()
        {
            GameOverEventArgs gameOverEventArgs = null;
            var chessBoard = new ChessBoard();
            var blackKnight = new Knight(Colour.Black);
            var whitePawn = new Pawn(Colour.White);
            var boardPosition1 = new BoardPosition("A1");
            var boardPosition2 = new BoardPosition("B3");
            chessBoard.SetInitialPosition(boardPosition1, blackKnight);
            chessBoard.SetInitialPosition(boardPosition2, whitePawn);

            chessBoard.GameOver += (sender, e) =>
            {
                gameOverEventArgs = e;
            };

            chessBoard.MakeMove(boardPosition1, boardPosition2);

            Assert.That(gameOverEventArgs, Is.Not.Null);
            Assert.That(gameOverEventArgs.Result, Is.EqualTo(GameResult.BlackWin));
        }
Exemple #7
0
        internal override MoveResult ValidateMove(
             ChessBoard chessBoard,
             BoardPosition from,
             BoardPosition to,
             out ExceptionReasonDetail exceptionReasonDetail)
        {
            exceptionReasonDetail = ExceptionReasonDetail.None;
             MoveResult result = MoveResult.Illegal;

             int fileDiff = Math.Abs(from.InternalFile - to.InternalFile);
             int rankDiff = Math.Abs(from.InternalRank - to.InternalRank);

             if ((fileDiff == 2 && rankDiff == 1) || (fileDiff == 1 && rankDiff == 2)) {
                 Square toSquare = chessBoard.GetSquare(to);
                 if (toSquare.ChessPiece == null || toSquare.ChessPiece.Colour != this.Colour) {
                     result = MoveResult.Valid;
                 }
             }

             return result;
        }
        /// <summary>
        /// Move a chess piece from one board position to another.
        /// </summary>
        /// <param name="fromBoardPosition">The board position to move a chess piece from</param>
        /// <param name="toBoardPosition">The board position to move a chess piece to</param>
        public void MakeMove(BoardPosition from, BoardPosition to)
        {
            Square fromSquare = GetSquare(from);
            Square toSquare = GetSquare(to);

            ChessPiece pieceBeingMoved = fromSquare.ChessPiece;

            if (pieceBeingMoved == null) {
                var ex = new ChessBoardException(ExceptionReason.FromSquareIsNotOccupied);
                throw ex;
            }

            GameResult? gameResult = null;
            ExceptionReasonDetail exceptionReasonDetail;
            MoveResult moveResult = pieceBeingMoved.ValidateMove(this, from, to, out exceptionReasonDetail);

            switch (moveResult) {

                case MoveResult.Valid:

                    // Does this move involve a piece being taken ?
                    if (toSquare.ChessPiece != null) {
                        ChessPiece takenPiece = toSquare.ChessPiece;
                        RaisePieceTaken(toSquare, takenPiece);
                        takenPiece.BoardPosition = null;
                        gameResult = (pieceBeingMoved.Colour == Colour.White) ? GameResult.WhiteWin : GameResult.BlackWin;
                    }

                    fromSquare.ChessPiece = null;
                    toSquare.ChessPiece = pieceBeingMoved;
                    pieceBeingMoved.BoardPosition = to;
                    RaiseMoveMade(from, to, pieceBeingMoved);
                    break;

                case MoveResult.Collision:
                    gameResult = GameResult.Draw;
                    break;

                case MoveResult.Illegal:
                    var ex = new ChessBoardException(ExceptionReason.IllegalMove, exceptionReasonDetail);
                    throw ex;

                default:
                    break;
            }

            // By convention, White always goes first so if we just moved
            // a Black piece, this must be the end of a round.
            // NOTE: There is nothing in the SpecFlow features regarding :-
            //       - which colour goes first
            //       - checking that turns alternate colour
            //       - checking the maximum number of rounds (meant to be 2)
            //       - etc.
            if (pieceBeingMoved.Colour == Colour.Black) {
                this.Round++;
            }

            if (gameResult.HasValue) {
                RaiseGameOver(gameResult.Value);
            }
        }
 /// <summary>
 /// Returns the Square at the given board position.
 /// </summary>
 /// <param name="boardPosition">The board position for which the Square should be returned</param>
 /// <returns>The Square at the given board position</returns>
 public virtual Square GetSquare(BoardPosition boardPosition)
 {
     return this.squares[boardPosition.InternalFile, boardPosition.InternalRank];
 }
 private void RaiseMoveMade(BoardPosition from, BoardPosition to, ChessPiece chessPiece)
 {
     var handler = this.MoveMade;
     if (handler != null) {
         var eventArgs = new MoveMadeEventArgs(from, to, chessPiece);
         handler(this, eventArgs);
     }
 }
        /// <summary>
        /// Add a chess piece to the board at a given position.
        /// </summary>
        /// <param name="boardPosition">The initial position at which to place the chess piece</param>
        /// <param name="chessPiece">The chess piece to be placed</param>
        public void SetInitialPosition(BoardPosition boardPosition, ChessPiece chessPiece)
        {
            Square square = GetSquare(boardPosition);

            if (square.ChessPiece != null) {
                var ex = new ChessBoardException(ExceptionReason.InitialPositionAlreadyOccupied);
                throw ex;
            }

            square.ChessPiece = chessPiece;
            chessPiece.BoardPosition = boardPosition;
        }
        public void SetInitialPosition_GivenTwoPiecesAtSameLocation_ThrowsException()
        {
            var chessBoard = new ChessBoard();
            var boardPosition = new BoardPosition("A1");
            chessBoard.SetInitialPosition(boardPosition, new Knight(Colour.Black));

            try {
                chessBoard.SetInitialPosition(boardPosition, new Pawn(Colour.White));
                Assert.Fail("Expected a ChessBoardException to be thrown!");
            }
            catch (ChessBoardException ex) {
                Assert.That(ex.ExceptionReason, Is.EqualTo(ExceptionReason.InitialPositionAlreadyOccupied));
            }
        }
        public void SetInitialPosition_GivenKnightAtA1_Succeeds()
        {
            var chessBoard = new ChessBoard();
            var boardPosition = new BoardPosition("A1");
            chessBoard.SetInitialPosition(boardPosition, new Knight(Colour.Black));

            Assert.That(chessBoard.GetSquare(boardPosition), Is.Not.Null);
            Assert.That(chessBoard.GetSquare(boardPosition).ChessPiece, Is.Not.Null);
            Assert.That(chessBoard.GetSquare(boardPosition).ChessPiece, Is.InstanceOf<Knight>());
            Assert.That(chessBoard.GetSquare(boardPosition).ChessPiece.Colour, Is.EqualTo(Colour.Black));
        }
 /// <summary>
 /// Initialises a new instance of the ChessPiece class with the given colour and initial board position.
 /// </summary>
 /// <param name="colour">The colour of the chess piece.</param>
 /// <param name="boardPosition">The initial board position of the chess piece.</param>
 public ChessPiece(Colour colour, BoardPosition boardPosition)
 {
     this.Colour = colour;
     this.BoardPosition = null;
     this.Name = string.Empty;
 }
 private bool CompareFields(BoardPosition rhs)
 {
     return (this.InternalFile == rhs.InternalFile &&
             this.InternalRank == rhs.InternalRank);
 }
 public MoveMadeEventArgs(BoardPosition from, BoardPosition to, ChessPiece chessPiece)
 {
     this.From = from;
     this.To = to;
     this.ChessPiece = chessPiece;
 }