public bool IsValidMove(CellId source, CellId target, IChessBoard board) { var sourceCell = board.GetCell(source); var targetCell = board.GetCell(target); return(IsValidMove(sourceCell, targetCell, board)); }
public void MovePiece(CellId source, CellId target) { if (!IsValidMove(source, target)) { throw new InvalidOperationException("Invalid move!"); } // Figure out if it is a castle operation. // var sourceCell = _chessboard.GetCell(source); var targetCell = _chessboard.GetCell(target); // We know it is a valid move. We just have to identify if it is a castle // operation. // if (sourceCell.PieceType == EChessPieceType.King && targetCell.PieceType == EChessPieceType.Rook && sourceCell.PieceColor == targetCell.PieceColor) { _chessboard.SwapPiece(source, target); } else { _chessboard.MovePiece(source, target); } nextTurn(); }
public void SetPiece(CellId identifier, EChessPieceType piece, EChessPieceColor color) { EChessPieceType oldPiece = _cells[identifier].PieceType; EChessPieceColor oldColor = _cells[identifier].PieceColor; _cells[identifier].SetPiece(piece, color); CellStatusChanged(this, new CellStatusChangedEventArgs(identifier, oldPiece, oldColor, piece, color)); }
private void SetValidMoveTargets(bool isValidMoveTarget, CellId sourceCell) { var validMoveTargets = _gameLogic.ValidMovesForCell(sourceCell); foreach (var moveTarget in validMoveTargets) { GetCell(moveTarget).IsValidMoveTarget = isValidMoveTarget; } }
public CellStatusChangedEventArgs(CellId identifier, EChessPieceType oldPiece, EChessPieceColor oldColor, EChessPieceType newPiece, EChessPieceColor newColor) { Identifier = identifier; OldPiece = oldPiece; NewPiece = newPiece; OldColor = oldColor; NewColor = newColor; }
// We need this for castling and other things. // public bool HasMoved(CellId cell) { // Just look through the history and check if some piece has moved to this cell. // foreach (var move in _moveHistory) { if (move.Target.Equals(cell)) { return(true); } } return(false); }
public void MovePiece(CellId source, CellId target) { if (!_gameRules.IsValidMove(source, target, this)) { throw new InvalidOperationException("This is an invalid move."); } var pieceType = _cells[source].PieceType; var pieceColor = _cells[source].PieceColor; SetPiece(target, pieceType, pieceColor); SetPiece(source, EChessPieceType.Empty, EChessPieceColor.Empty); _moveHistory.AddMove(new Move(source, target)); }
public void SwapPiece(CellId source, CellId target) { if (!_gameRules.IsValidMove(source, target, this)) { throw new InvalidOperationException("This is an invalid move."); } var pieceType1 = _cells[source].PieceType; var pieceType2 = _cells[target].PieceType; var pieceColor1 = _cells[source].PieceColor; var pieceColor2 = _cells[target].PieceColor; SetPiece(target, pieceType1, pieceColor1); SetPiece(source, pieceType2, pieceColor2); // Can we use this for castling?? // _moveHistory.AddMove(new Move(source, target)); }
private void Cell_CellSelected(object sender, CellId selectedCellIdentifier) { // XXX: Implement the move logic here. // Hint: Use the _gameLogic object to check for valid moves and for moving pieces. // If a user selects a piece, we remember the selected piece using the _selectedPiece // field. If a user then selects a valid field, we move the piece. If the user selects // an invalid field, we reset the selection. // var targetCell = GetCell(selectedCellIdentifier); if (_selectedPiece == null) { if (!CanActivePlayerMove(targetCell.ChessPieceColor)) { return; } _selectedPiece = targetCell; _selectedPiece.IsCellSelected = true; SetValidMoveTargets(true, _selectedPiece.Identifier); return; } var sourceCell = _selectedPiece; _selectedPiece.IsCellSelected = false; _selectedPiece = null; SetValidMoveTargets(false, sourceCell.Identifier); bool isValidMove = _gameLogic .IsValidMove(sourceCell.Identifier, targetCell.Identifier); if (!isValidMove) { return; } _gameLogic.MovePiece(sourceCell.Identifier, targetCell.Identifier); }
public IReadOnlyList <CellId> ValidMovesForCell(CellId cellId, IChessBoard board) { var validMoveList = new List <CellId>(); var source = board.GetCell(cellId); for (int row = 0; row < board.NumRows; row++) { for (int col = 0; col < board.NumCols; col++) { // Figure out the status of the cell. // var target = board.GetCell(CellId.Create(row, col)); if (IsValidMove(source, target, board)) { validMoveList.Add(CellId.Create(row, col)); } } } return(validMoveList); }
public void MovePiece(CellId source, CellId target) { if (!IsValidMove(source, target)) { throw new InvalidOperationException("Invalid move!"); } // Figure out if it is a castle operation. // var sourceCell = _chessboard.GetCell(source); var targetCell = _chessboard.GetCell(target); // We know it is a valid move. We just have to identify if it is a castle // operation. // if (sourceCell.PieceType == EChessPieceType.King && targetCell.PieceType == EChessPieceType.Rook && sourceCell.PieceColor == targetCell.PieceColor) { _chessboard.SwapPiece(source, target); } else { if (targetCell.PieceColor != sourceCell.PieceColor) // The player captured a piece { PieceCaptured(this, new PieceCapturedEventArgs(targetCell.PieceType, targetCell.PieceColor)); // Check if the king was captured. // if (targetCell.PieceType == EChessPieceType.King) { GameFinished(this, new GameEndedEventArgs(ActivePlayer)); } } _chessboard.MovePiece(source, target); } nextTurn(); }
private void setupBlackBishopRules() { var blackBishopRules = GameRule.Create().Filter(x => x.PieceColor == EChessPieceColor.Black && x.PieceType == EChessPieceType.Bishop); blackBishopRules.InvalidMove((s, t, c) => { // Can not move to a field occupied by a black piece. // return(t.PieceColor == EChessPieceColor.Black); }); blackBishopRules.InvalidMove((s, t, c) => { // Can not move past another piece. // int colDiff = s.ColIndex - t.ColIndex; int rowDiff = s.RowIndex - t.RowIndex; if (Math.Abs(colDiff) != Math.Abs(rowDiff)) { return(false); // Check its a diagonal move } int stepRow = rowDiff > 0 ? -1 : 1; int stepCol = colDiff > 0 ? -1 : 1; // Check there is no piece on the way to the target. // for (int step = 1; t.ColIndex != s.ColIndex + stepCol * step; step++) { int row = s.RowIndex + stepRow * step; int col = s.ColIndex + stepCol * step; // We reached the target it is not an invalid move. // if (row == t.RowIndex || col == t.RowIndex) { return(false); } // We reached another piece, but it can not be the target of our move // therefore this move is not valid. // var cell = c.GetCell(CellId.Create(row, col)); if (cell.PieceType != EChessPieceType.Empty) { return(true); } } return(false); }); blackBishopRules.ValidMove((s, t, c) => { // Bishop can move diagonally to take any piece. // int colDiff = Math.Abs(s.ColIndex - t.ColIndex); int rowDiff = Math.Abs(s.RowIndex - t.RowIndex); if (colDiff != rowDiff) { return(false); } return(true); }); _gameRules.Add(blackBishopRules); }
private CellId keyFor(int row, int col) { return(CellId.Create(row, col)); }
public bool IsValidMove(CellId source, CellId target) { return(_gameRules.IsValidMove(source, target, this)); }
private CellStatusViewModel GetCell(CellId cellId) { return(Cells[cellId.Row][cellId.Col]); }
public bool IsValidMove(CellId source, CellId target) { return(_gameRules.IsValidMove(source, target, _chessboard)); }
private void Cell_CellSelected(object sender, CellId selectedCellIdentifier) { if (_isGameFinished) { return; } // If an empty cell or a cell of the opponent color was selected // unselect the previous cell. // var cell = fetchCell(selectedCellIdentifier); if (_isPieceSelected == true) // The user previously selected a valid piece. { if (_gameLogic.IsValidMove(_selectedPiece.Identifier, selectedCellIdentifier)) { _gameLogic.MovePiece(_selectedPiece.Identifier, selectedCellIdentifier); unselectAllCells(); clearValidMoves(); _isPieceSelected = false; ActivePlayer = _gameLogic.ActivePlayer; } else { // It is not a valid move. If another valid piece was selected change the selection. // if (!cell.IsEmpty) { if (ActivePlayer == EActivePlayer.Black && cell.ChessPieceColor == EChessPieceColor.Black || ActivePlayer == EActivePlayer.White && cell.ChessPieceColor == EChessPieceColor.White) { unselectAllCells(); clearValidMoves(); _selectedPiece = cell; _selectedPiece.IsCellSelected = true; displayValidMovesForPiece(_selectedPiece); } } } } if (_isPieceSelected == false) // We have no selected piece. { if (cell.IsEmpty) // Nothing to do here { return; } // Check the user selected a valid piece. // if (_gameLogic.ActivePlayer == EActivePlayer.White && cell.ChessPieceColor == EChessPieceColor.White || _gameLogic.ActivePlayer == EActivePlayer.Black && cell.ChessPieceColor == EChessPieceColor.Black) { _selectedPiece = cell; _selectedPiece.IsCellSelected = true; _isPieceSelected = true; displayValidMovesForPiece(_selectedPiece); } // User selected a an invalid piece. // else { return; } } }
private void setupQueenRules() { var queenRules = GameRule.Create().Filter(x => x.PieceType == EChessPieceType.Queen); queenRules.InvalidMove((s, t, c) => { // Can not move to our own position. This would cause an indexing issue. // if (s.ColIndex == t.ColIndex && s.RowIndex == t.RowIndex) { return(true); } // Can not move past another piece. // int colDiff = s.ColIndex - t.ColIndex; int rowDiff = s.RowIndex - t.RowIndex; int stepRow = rowDiff > 0 ? -1 : 1; int stepCol = colDiff > 0 ? -1 : 1; if (colDiff == 0) { stepCol = 0; } if (rowDiff == 0) { stepRow = 0; } // Check there is no piece on the way to the target. // for (int step = 1; ; step++) { int row = s.RowIndex + stepRow * step; int col = s.ColIndex + stepCol * step; if (row < 0 || row >= c.NumRows || col < 0 || col >= c.NumCols) { return(true); } // We reached the target it is not an invalid move. // if (row == t.RowIndex && col == t.ColIndex) { return(false); } if (row == c.NumCols - 1 && col == c.NumRows - 1) { return(true); } // We reached another piece, but it can not be the target of our move // therefore this move is not valid. // var cell = c.GetCell(CellId.Create(row, col)); if (cell.PieceType != EChessPieceType.Empty) { return(true); } } }); queenRules.InvalidMove((s, t, c) => { // Can not move to our own position. This would cause an indexing issue. // if (s.ColIndex == t.ColIndex && s.RowIndex == t.RowIndex) { return(true); } // Can not move past another piece. // int colDiff = s.ColIndex - t.ColIndex; int rowDiff = s.RowIndex - t.RowIndex; if (Math.Abs(colDiff) != Math.Abs(rowDiff)) { return(false); // Check its a diagonal move } int stepRow = rowDiff > 0 ? -1 : 1; int stepCol = colDiff > 0 ? -1 : 1; // Check there is no piece on the way to the target. // for (int step = 1; t.ColIndex != s.ColIndex + stepCol * step; step++) { int row = s.RowIndex + stepRow * step; int col = s.ColIndex + stepCol * step; // We reached the target it is not an invalid move. // if (row == t.RowIndex || col == t.ColIndex) { return(false); } if (row == c.NumCols - 1 && col == c.NumRows - 1) { return(true); } // We reached another piece, but it can not be the target of our move // therefore this move is not valid. // var cell = c.GetCell(CellId.Create(row, col)); if (cell.PieceType != EChessPieceType.Empty) { return(true); } } return(false); }); queenRules.ValidMove((s, t, c) => { // Rook can move diagonally or vertically. // int colDiff = Math.Abs(s.ColIndex - t.ColIndex); int rowDiff = Math.Abs(s.RowIndex - t.RowIndex); if (colDiff == 0 || rowDiff == 0) { return(true); } return(false); }); queenRules.ValidMove((s, t, c) => { // Bishop can move diagonally to take any piece. // int colDiff = Math.Abs(s.ColIndex - t.ColIndex); int rowDiff = Math.Abs(s.RowIndex - t.RowIndex); if (colDiff != rowDiff) { return(false); } return(true); }); _gameRules.Add(queenRules); }
private void setupKingRules() { var kingRules = GameRule.Create().Filter(x => x.PieceType == EChessPieceType.King); kingRules.InvalidMove((s, t, c) => { if (t.PieceColor != s.PieceColor) { return(false); } // Can not move to a piece of the same color unless it is a rook. // Some more castle rules are checked below. // if (t.PieceColor == s.PieceColor && t.PieceType == EChessPieceType.Rook) { return(false); } return(true); }); kingRules.ValidMove((s, t, c) => { int colDiff = Math.Abs(s.ColIndex - t.ColIndex); int rowDiff = Math.Abs(s.RowIndex - t.RowIndex); return(colDiff <= 1 && rowDiff <= 1); }); // Setup up the castle, it is only possible if the king and the rook have not been moved before and // there is no piece between the king and the rook. // kingRules.ValidMove((s, t, c) => { // Check the target is a friendly rook. // if (t.PieceType != EChessPieceType.Rook || s.PieceColor != t.PieceColor) { return(false); } // Check the rook and the king have not been moved. // if (c.HasMoved(s.Identifier) || c.HasMoved(t.Identifier)) { return(false); } // Check there is no piece between the king and the rook. // int colDiff = s.ColIndex - t.ColIndex; int colStep = colDiff > 0 ? -1 : 1; for (int step = 1; s.ColIndex + step * colStep != t.ColIndex; step++) { int col = s.ColIndex + step * colStep; var cell = c.GetCell(CellId.Create(s.RowIndex, col)); if (cell.PieceType != EChessPieceType.Empty) { return(false); } } return(true); }); _gameRules.Add(kingRules); }
private CellStatusViewModel fetchCell(CellId identifier) { return(Cells[identifier.Row][identifier.Col]); }
public IReadOnlyList <CellId> ValidMovesForCell(CellId source) { return(_gameRules.ValidMovesForCell(source, _chessboard)); }
public Move(CellId source, CellId target) { Source = source; Target = target; }
public ChessCellModel GetCell(CellId cellId) { return(_cells[cellId]); }