void RefreshBoard(GameState.MatchState matchState, ChessData.Coordinate?selected)
        {
            CurrentMatchState = matchState;
            StatusText.text   = string.Format("{0} ({1})",
                                              matchState.IsSelfTurn() ? "Your Turn" : "Their Turn",
                                              matchState.Board.GetTurnColor() == ChessData.ChessPieceColor.White ? "white" : "black");

            for (int r = 0; r < 8; r++)
            {
                for (int c = 0; c < 8; c++)
                {
                    foreach (Transform child in TransformGrid[r, c])
                    {
                        Destroy(child.gameObject);
                    }
                }
            }

            if (matchState.Board.PreviousMove.IsCheckMate)
            {
                TitleText.text  = "Game Finished";
                StatusText.text = string.Format("{0} won!", matchState.IsSelfTurn() ? "They" : "You");
                return;
            }

            IEnumerable <ChessData.ChessMove> moves;
            var moveDestinations = new HashSet <ChessData.Coordinate>();

            if (selected.HasValue)
            {
                moves = matchState.Board.GetPossibleMoves(selected.Value);
                //TODO: server.GetPossibleMoves(board_id, selected.value)
            }
            else
            {
                moves = new HashSet <ChessData.ChessMove>();
            }
            foreach (var move in moves)
            {
                moveDestinations.Add(move.To);
            }

            // Fill in pieces, except those that are move destinations
            for (int c = 0; c < 8; c++)
            {
                for (int r = 0; r < 8; r++)
                {
                    var  coordinate           = new ChessData.Coordinate(r, c);
                    bool isSelectedCoordinate = selected.HasValue && selected.Value.Equals(coordinate);
                    bool isMoveDestination    = moveDestinations.Contains(coordinate);

                    ChessData.ChessPiece piece = matchState.Board.GetPieceAtCoordinate(coordinate);
                    // pieces that are move destinations are handled later because clicking on them has movement behavior.
                    if (piece.Type != ChessData.ChessPieceType.None && !isMoveDestination)
                    {
                        Color pieceHighlight = isSelectedCoordinate ? Color.green : Color.white;
                        Image pieceImage     = prefabToPieceImage(piece, pieceHighlight);
                        pieceImage.transform.SetParent(TransformGrid[r, c], false);
                        // Only allow player to make moves if it is their turn. Games against local
                        // player allow both players to make a move on the same device.
                        if (matchState.IsSelfTurn() || matchState.Opponent.IsLocalOpponent())
                        {
                            pieceImage.GetComponent <Button>().onClick.AddListener(delegate
                            {
                                if (selected == null)
                                {
                                    RefreshBoard(matchState, coordinate);
                                }
                                else if (selected.Value.Equals(coordinate))
                                {
                                    RefreshBoard(matchState, null);
                                }
                                else
                                {
                                    RefreshBoard(matchState, coordinate);
                                }
                            });
                        }
                    }
                }
            }

            // Fill in pieces that are move destinations
            foreach (var move in moves)
            {
                bool putsUserInCheck = matchState.Board.TryApplyMove(move);
                var  newMatchState   = new GameState.MatchState(
                    matchState.Opponent,
                    matchState.Board,
                    //TODO: TryApplyMove(move, board_id)
                    matchState.SelfIsWhite,
                    matchState.Identifier);

                if (!putsUserInCheck)
                {
                    bool isOpponentPiece = matchState.Board.GetPieceAtCoordinate(move.To).Type != ChessData.ChessPieceType.None;
                    //TODO: GetPieceAtCoordinate(board_id, coord)
                    Color pieceHighlight = isOpponentPiece ? Color.red : Color.blue;
                    var   fromPiece      = matchState.Board.GetPieceAtCoordinate(move.From);
                    Image pieceImage     = prefabToPieceImage(fromPiece, pieceHighlight);
                    pieceImage.transform.SetParent(TransformGrid[move.To.Row, move.To.Column], false);

                    // Only allow player to make moves if it is their turn. Games against local
                    // player allow both players to make a move on the same device.
                    if (matchState.IsSelfTurn() || matchState.Opponent.IsLocalOpponent())
                    {
                        pieceImage.GetComponent <Button>().onClick.AddListener(delegate
                        {
                            // GameManager will handler whether or not we are saving a local or multiplayer
                            // game, and will notify us of the updated state via our
                            // CurrentMatchStateAvailableHandler
                            StatusText.text = "Saving Match...";
                            GameManager.Instance.UpdateMatchState(newMatchState);
                        });
                    }
                }
            }
        }
        void RefreshBoard(GameState.MatchState matchState, BoardState.Coordinate? selected)
        {
            CurrentMatchState = matchState;
            StatusText.text = string.Format("{0} ({1})",
                matchState.IsSelfTurn() ? "Your Turn" : "Their Turn",
                matchState.BoardState.TurnColor == BoardState.ChessPieceColor.White ? "white" : "black");

            for (int r = 0; r < 8; r++)
            {
                for (int c = 0; c < 8; c++)
                {
                    foreach (Transform child in TransformGrid[r, c])
                    {
                        Destroy(child.gameObject);
                    }
                }
            }

            if (matchState.BoardState.PreviousMove.IsCheckMate)
            {
                TitleText.text = "Game Finished";
                StatusText.text = string.Format("{0} won!", matchState.IsSelfTurn() ? "They" : "You");
                return;
            }

            HashSet<BoardState.ChessMove> moves;
            var moveDestinations = new HashSet<BoardState.Coordinate>();
            if (selected.HasValue)
            {
                moves = matchState.BoardState.GetPossibleMoves(selected.Value);
            }
            else
            {
                moves = new HashSet<BoardState.ChessMove>();
            }
            foreach (var move in moves)
            {
                moveDestinations.Add(move.To);
            }

            // Fill in pieces, except those that are move destinations
            for (int c = 0; c < 8; c++)
            {
                for (int r = 0; r < 8; r++)
                {
                    var coordinate = new BoardState.Coordinate(r, c);
                    bool isSelectedCoordinate = selected.HasValue && selected.Value.Equals(coordinate);
                    bool isMoveDestination = moveDestinations.Contains(coordinate);

                    BoardState.ChessPiece piece = matchState.BoardState.GetPieceAtCoordinate(coordinate);
                    // pieces that are move destinations are handled later because clicking on them has movement behavior.
                    if (piece.Type != BoardState.ChessPieceType.None && !isMoveDestination)
                    {
                        Color pieceHighlight = isSelectedCoordinate ? Color.green : Color.white;
                        Image pieceImage = prefabToPieceImage(piece, pieceHighlight);
                        pieceImage.transform.SetParent(TransformGrid[r, c], false);
                        // Only allow player to make moves if it is their turn. Games against local
                        // player allow both players to make a move on the same device.
                        if (matchState.IsSelfTurn() || matchState.Opponent.IsLocalOpponent())
                        {
                            pieceImage.GetComponent<Button>().onClick.AddListener(delegate
                            {
                                if (selected == null)
                                {
                                    RefreshBoard(matchState, coordinate);
                                }
                                else if (selected.Value.Equals(coordinate))
                                {
                                    RefreshBoard(matchState, null);
                                }
                                else
                                {
                                    RefreshBoard(matchState, coordinate);
                                }
                            });
                        }
                    }
                }
            }

            // Fill in pieces that are move destinations
            foreach (var move in moves)
            {
                bool putsUserInCheck;
                var newMatchState = new GameState.MatchState(
                    matchState.Opponent,
                    matchState.BoardState.TryApplyMove(move, out putsUserInCheck),
                    matchState.SelfIsWhite,
                    matchState.Identifier);

                if (!putsUserInCheck)
                {
                    bool isOpponentPiece = matchState.BoardState.GetPieceAtCoordinate(move.To).Type != BoardState.ChessPieceType.None;
                    Color pieceHighlight = isOpponentPiece ? Color.red : Color.blue;
                    BoardState.ChessPiece fromPiece = matchState.BoardState.GetPieceAtCoordinate(move.From);
                    Image pieceImage = prefabToPieceImage(fromPiece, pieceHighlight);
                    pieceImage.transform.SetParent(TransformGrid[move.To.Row, move.To.Column], false);

                    // Only allow player to make moves if it is their turn. Games against local
                    // player allow both players to make a move on the same device.
                    if (matchState.IsSelfTurn() || matchState.Opponent.IsLocalOpponent())
                    {
                        pieceImage.GetComponent<Button>().onClick.AddListener(delegate
                        {
                            // GameManager will handler whether or not we are saving a local or multiplayer
                            // game, and will notify us of the updated state via our
                            // CurrentMatchStateAvailableHandler
                            StatusText.text = "Saving Match...";
                            GameManager.Instance.UpdateMatchState(newMatchState);
                        });
                    }
                }
            }
        }