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)); }
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)); }
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; }