protected void initMap()
    {
        MapData map = GameState.map;

        numRows = map.numRows;
        numCols = map.numCols;
        path    = new List <ViewTile>();
        grid    = new ViewTile[numRows, numCols];

        // Generate tiles
        float topEdge  = (float)(spacing * (numRows / 2.0 - 0.5));
        float leftEdge = (float)-(spacing * (numCols / 2.0 - 0.5));

        for (int i = 0; i < numRows; ++i)
        {
            GameObject row = new GameObject("row");
            row.transform.parent        = gameObject.transform;
            row.transform.localPosition = new Vector3(0, topEdge - (spacing * i), 0);
            for (int j = 0; j < numCols; ++j)
            {
                ViewTile tile = Instantiate(tileScript);
                tile.transform.parent        = row.transform;
                tile.transform.localPosition = new Vector3(leftEdge + (spacing * j), 0, 0);
                tile.transform.localScale    = new Vector3(scaling, scaling, 0);
                tile.tileData.coord          = new Coord(i, j);
                tile.mapScript = this;
                grid[i, j]     = tile;
            }
        }
        // Set tile data
        for (int i = 0; i < numRows; ++i)
        {
            for (int j = 0; j < numCols; ++j)
            {
                grid[i, j].tileData = map.getTileData(i, j);
            }
        }

        // Set path
        TileData        td;
        List <TileData> map_path = map.getPath();

        td = map_path[0];
        grid[td.coord.row, td.coord.col].setSprite(TSprites.startTile);
        path.Add(grid[td.coord.row, td.coord.col]);
        for (int i = 1; i < map_path.Count - 1; ++i)
        {
            td = map_path[i];
            grid[td.coord.row, td.coord.col].setSprite(TSprites.decideSprite(td.startDirection, td.endDirection));
            path.Add(grid[td.coord.row, td.coord.col]);
        }
        td = map_path[map_path.Count - 1];
        grid[td.coord.row, td.coord.col].setSprite(TSprites.endTile);
        path.Add(grid[td.coord.row, td.coord.col]);
    }
    public void onTileClick(BuildTile tile)
    {
        if (disabled)
        {
            return;
        }
        // Check for start tile.
        if (path.Count == 0)
        {
            if (tile.coord.col == 0)
            {
                tile.setSprite(TSprites.startTile);
                tile.state          = TileData.State.PATH;
                tile.startDirection = TileData.Direction.LEFT;
                tile.endDirection   = TileData.Direction.RIGHT;
                path.Add(tile);
                validTiles[0] = null;
                validTiles[1] = getTile(tile.coord.row, tile.coord.col + 1);
                validTiles[2] = null;
                validTiles[1].highlight();
                instructions.text = "Build path for monsters attacking you";
            }
            return;
        }

        // Check for subsequent tiles
        BuildTile prev  = path[path.Count - 1];
        int       valid = Array.IndexOf(validTiles, tile);

        if (valid < 0 && !tile.Equals(prev))
        {
            return;
        }

        // Clear valid tiles.
        for (int i = 0; i < validTiles.Length; ++i)
        {
            if (validTiles[i] != null)
            {
                validTiles[i].unhighlight();
                validTiles[i] = null;
            }
        }

        // check if is undo.
        if (tile.Equals(prev))   // Undo tile.
        {
            tile.startDirection = TileData.Direction.UNSET;
            tile.setSprite(TSprites.emptyTile);
            tile.state = TileData.State.EMPTY;
            path.RemoveAt(path.Count - 1);
            readyButton.interactable = false;
            if (path.Count == 0)
            {
                instructions.text = "Pick your starting point";
                return;
            }
            tile = path[path.Count - 1];
            if (path.Count == 1)
            {
                validTiles[0] = null;
                validTiles[1] = getTile(tile.coord.row, tile.coord.col + 1);
                validTiles[2] = null;
                validTiles[1].highlight();
                instructions.text = "Build path for monsters attacking you";
                return;
            }
            else
            {
                tile.endDirection = TileData.Direction.UNSET;
            }
        }
        else     // Adding tile.
        // Set directions.
        {
            switch (valid)
            {
            case 0:     // Going up.
                prev.endDirection   = TileData.Direction.UP;
                tile.startDirection = TileData.Direction.DOWN;
                break;

            case 1:     // Going right.
                prev.endDirection   = TileData.Direction.RIGHT;
                tile.startDirection = TileData.Direction.LEFT;
                break;

            case 2:     // Going down.
                prev.endDirection   = TileData.Direction.DOWN;
                tile.startDirection = TileData.Direction.UP;
                break;
            }

            // Set the prev tile sprite. (2nd tile ownwards)
            if (path.Count >= 2)
            {
                Sprite prev_s = TSprites.decideSprite(prev.startDirection, prev.endDirection);
                if (prev_s != null)
                {
                    prev.setSprite(prev_s);
                }
            }

            tile.state = TileData.State.PATH;
            path.Add(tile);

            // Check if is last tile.
            if (tile.coord.col + 1 >= numCols)
            {
                tile.setSprite(TSprites.endTile);
                instructions.text        = "Path is complete, are you ready?";
                readyButton.interactable = true;
                return;
            }
        }

        // Set sprite
        Sprite s = TSprites.decideSprite(tile.startDirection, tile.endDirection);

        if (s != null)
        {
            tile.setSprite(s);
        }

        // Set valid tiles
        int cur_row = tile.coord.row;
        int cur_col = tile.coord.col;
        // Up
        BuildTile v_tile = getTile(cur_row - 1, cur_col);

        if (v_tile != null && !path.Contains(v_tile))
        {
            v_tile.highlight();
            validTiles[0] = v_tile;
        }
        // Right
        v_tile = getTile(cur_row, cur_col + 1);
        if (v_tile != null && !path.Contains(v_tile))
        {
            v_tile.highlight();
            validTiles[1] = v_tile;
        }
        // Down
        v_tile = getTile(cur_row + 1, cur_col);
        if (v_tile != null && !path.Contains(v_tile))
        {
            v_tile.highlight();
            validTiles[2] = v_tile;
        }
    }