public bool IsValidMove(CellId source, CellId target, IChessBoard board)
        {
            var sourceCell = board.GetCell(source);
            var targetCell = board.GetCell(target);

            return(IsValidMove(sourceCell, targetCell, board));
        }
Ejemplo n.º 2
0
        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));
        }
Ejemplo n.º 4
0
        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));
        }
Ejemplo n.º 9
0
        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);
        }
Ejemplo n.º 11
0
        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));
 }
Ejemplo n.º 15
0
 private CellStatusViewModel GetCell(CellId cellId)
 {
     return(Cells[cellId.Row][cellId.Col]);
 }
Ejemplo n.º 16
0
 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);
        }
Ejemplo n.º 20
0
 private CellStatusViewModel fetchCell(CellId identifier)
 {
     return(Cells[identifier.Row][identifier.Col]);
 }
Ejemplo n.º 21
0
 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]);
 }