Пример #1
0
    private bool AttemptMove(Square destination)
    {
        if (_selectedSquare == null)
        {
            throw new NullReferenceException("selected square null while attempting move!");
        }
        Piece selectedPiece = _selectedSquare.piece;
        int   rowChange     = destination.row - _selectedSquare.row;
        int   columnChange  = destination.column - _selectedSquare.column;
        bool  moveLegal     = false;
        bool  castle        = false;

        switch (selectedPiece.type)
        {
        case "Pawn": {
            int movementDirection = selectedPiece.color == "White" ? 1 : -1;
            if (rowChange == 2 * movementDirection && columnChange == 0 && selectedPiece.movesMade == 0 &&
                (_squares[destination.row - movementDirection][destination.column].piece == null))
            {
                //this allows first step of size 2
            }
            else if (rowChange != movementDirection)
            {
                Debug.Log("Invalid move, pawn can only move forwards, by 1 or at first 2 squares!");
                return(false);
            }
            if (columnChange == 0)
            {
                //Move pawn forwards
                if (destination.piece == null)
                {
                    moveLegal = true;
                    break;
                }
                Debug.Log("Invalid move, a piece is blocking your way!");
                return(false);
            }
            if (columnChange == 1 || columnChange == -1)
            {
                //move diagonally only on top of other pieces!
                if (destination.piece != null && destination.piece.color != _turn)
                {
                    moveLegal = true;
                    break;
                }
                Debug.Log("Invalid move, no pieces to attack here!");
                return(false);
            }
            Debug.Log("Pawn can only move 1 square diagonally!");
            return(false);
        }

        case "Rook": {
            if (rowChange != 0 && columnChange != 0)
            {
                Debug.Log("Rook can only move up, down, left, and right!");
                return(false);
            }
            if (rowChange == 0)
            {
                int row  = _selectedSquare.row;
                int sign = Math.Sign(columnChange);
                for (int column = _selectedSquare.column + sign;
                     Math.Abs(column - _selectedSquare.column) < Math.Abs(columnChange); column += sign)
                {
                    if (_squares[row][column].piece == null)
                    {
                        continue;
                    }
                    Debug.Log("Pieces in the way, cannot go over them!" + row + ", " + column);
                    return(false);
                }
            }
            if (columnChange == 0)
            {
                int column = _selectedSquare.column;
                int sign   = Math.Sign(rowChange);
                for (int row = _selectedSquare.row + sign; Math.Abs(row - _selectedSquare.row) < Math.Abs(rowChange); row += sign)
                {
                    if (_squares[row][column].piece == null)
                    {
                        continue;
                    }
                    Debug.Log("Pieces in the way of rook!" + row + ", " + column);
                    return(false);
                }
            }
            //Move is legal
            moveLegal = true;
            break;
        }

        case "Bishop": {
            if (Math.Abs(rowChange) != Math.Abs(columnChange))
            {
                Debug.Log("Bishops can only move diagonally!");
                return(false);
            }
            int rowSign    = Math.Sign(rowChange);
            int columnSign = Math.Sign(columnChange);
            for (int inc = 1; inc < Math.Abs(rowChange); inc++)
            {
                if (_squares[_selectedSquare.row + rowSign * inc][_selectedSquare.column + columnSign * inc].piece == null)
                {
                    continue;
                }
                return(false);
            }
            //Move legal
            moveLegal = true;
            break;
        }

        case "Knight": {
            if (!((Math.Abs(rowChange) == 2 && Math.Abs(columnChange) == 1) ||
                  (Math.Abs(rowChange) == 1 && Math.Abs(columnChange) == 2)))
            {
                Debug.Log("Knight can only move in an L patter!");
                return(false);
            }
            moveLegal = true;
            break;
        }

        case "Queen": {
            if (!((Math.Abs(rowChange) == Math.Abs(columnChange)) || rowChange == 0 || columnChange == 0))
            {
                Debug.Log("Queen can only move in the 8 main directions!");
                return(false);
            }
            int rowSign    = Math.Sign(rowChange);
            int columnSign = Math.Sign(columnChange);
            for (int inc = 1; inc < Math.Abs(rowChange); inc++)
            {
                if (_squares[_selectedSquare.row + rowSign * inc][_selectedSquare.column + columnSign * inc].piece == null)
                {
                    continue;
                }
                Debug.Log("Pieces in the way of Queen!");
                return(false);
            }
            moveLegal = true;
            break;
        }

        case "King": {
            if (Math.Abs(rowChange) > 1 || Math.Abs(columnChange) > 1)
            {
                if (rowChange == 0 && Math.Abs(columnChange) == 2 && _selectedSquare.row % 7 == 0 && selectedPiece.movesMade == 0)
                {
                    //Allow castling
                    int    rookColumn = columnChange == 2 ? 7 : 0;
                    Square rookSquare = _squares[_selectedSquare.row][rookColumn];
                    if (rookSquare.piece != null && rookSquare.piece.type.Equals("Rook") && rookSquare.piece.movesMade == 0)
                    {
                        //King and rook both there
                        for (int col = _selectedSquare.column + Math.Sign(columnChange);
                             col == 1 || col == 6; col += Math.Sign(columnChange))
                        {
                            if (_squares[_selectedSquare.row][col].piece == null)
                            {
                                continue;
                            }
                            Debug.Log("Pieces in the way, cannot castle!");
                            return(false);
                        }
                        //If this is reached the move is legal, do castle;
                        castle = true;
                    }
                    else
                    {
                        Debug.Log("King cannot castle without rook!");
                        return(false);
                    }
                }
                else
                {
                    Debug.Log("King can only move 1 square in each direction!");
                    return(false);
                }
            }
            for (int i = -1; i < 2; i++)
            {
                for (int j = -1; j < 2; j++)
                {
                    int   rowIndex    = Mathf.Clamp(destination.row + i, 0, 7);
                    int   columnIndex = Mathf.Clamp(destination.column + j, 0, 7);
                    Piece temp        = _squares[rowIndex][columnIndex].piece;
                    if (temp == null || temp.type != "King" || temp.color == _turn)
                    {
                        continue;
                    }
                    Debug.Log("King can't move close to the opposing king!");
                    return(false);
                }
            }
            moveLegal = true;
            if (castle)
            {
                DoMove(_selectedSquare.row, columnChange == 2 ? 7 : 0,
                       _selectedSquare.row, destination.column - Math.Sign(columnChange),
                       false, true);
            }
            break;
        }

        default:
            Debug.Log("This should never happen!");
            break;
        }
        //return false if this move is not legal
        if (!moveLegal)
        {
            return(false);
        }

        selectedPiece.movesMade++;
        string destroyedPieceType  = "None";
        string destroyedPieceColor = "None";

        if (destination.piece != null)
        {
            if (destination.piece.color == _turn)
            {
                Debug.Log("Cannot destroy own piece!");
                return(false);
            }
            destroyedPieceType  = destination.piece.type;
            destroyedPieceColor = destination.piece.color;
            if (destination.piece.type.Equals("King"))
            {
                _gameOver = true;
            }
            StartCoroutine(DestroyPiece(destination.piece.gameObject));
        }
        destination.piece     = selectedPiece;
        _selectedSquare.piece = null;
        Transform destinationTransform   = destination.transform;
        Transform selectedPieceTransform = selectedPiece.transform;

        selectedPieceTransform.parent = destinationTransform;
        Vector3 destinationPosition = destinationTransform.position;
        Vector3 startSquarePosition = _selectedSquare.transform.position;

        _replayManager.DoMove(_selectedSquare.row, _selectedSquare.column,
                              destination.row, destination.column, destroyedPieceType, destroyedPieceColor, castle);
        StartCoroutine(MovePiece(selectedPieceTransform,
                                 new Vector2(destinationPosition.x, destinationPosition.z),
                                 new Vector2(startSquarePosition.x, startSquarePosition.z)));
        return(true);
    }