#include <Header.hpp>

const int MAXN      = 50;
const int dir[4][2] = {{1, 0}, {0, 1}, {-1, 0}, {0, -1}};

char G[MAXN][MAXN];
int  dist[MAXN][MAXN], h, w;

bool onBoard(int x, int y) { return x >= 0 && y >= 0 && x < h && y < w; }

void bfs(int startX, int startY)
{
    memset(dist, INFC, sizeof(dist));
    // io.WA(dist, h, w);
    queue<pair<int, int>> q;
    while (!q.empty()) q.pop();
    q.push({startX, startY});
    dist[startX][startY] = 0;
    while (!q.empty())
    {
        pair<int, int> k = q.front();
        q.pop();
        for (int i = 0; i < 4; i++)
        {
            int tx = k.first + dir[i][0];
            int ty = k.second + dir[i][1];
            if (onBoard(tx, ty) && G[tx][ty] == '.' && dist[tx][ty] > dist[k.first][k.second] + 1)
            {
                dist[tx][ty] = dist[k.first][k.second] + 1;
                q.push({tx, ty});
            }
        }
        // io.WA(dist, h, w);
    }
}

int main()
{
    io >> h >> w;
    io.RA(G, h, w);
    for (int i = 0; i < h; i++)
        for (int j = 0; j < w; j++)
            if (G[i][j] == '.')
            {
                bfs(i, j);
                goto out1;
            }
out1:
    int ax = 0, ay = 0;
    for (int i = 0; i < h; i++)
        for (int j = 0; j < w; j++)
            if (dist[i][j] != INF && dist[i][j] > dist[ax][ay]) ax = i, ay = j;
    bfs(ax, ay);
    // io.WL(ax, ay);
    ax = 0, ay = 0;
    for (int i = 0; i < h; i++)
        for (int j = 0; j < w; j++)
            if (dist[i][j] != INF && dist[i][j] > dist[ax][ay]) ax = i, ay = j;
    io.WL(dist[ax][ay]);
    return 0;
}