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