#include <bits/stdc++.h>
using namespace std;
#define f first
#define s second
#define pb push_back
typedef long long ll;
typedef unsigned long long ull;
typedef unsigned long long ull;
typedef pair<int, int> pii;
typedef vector<int> vi;
typedef pair<ll, ll> pll;
typedef vector<pii> vpii;
typedef vector<pll> vpll;
typedef vector<ll> vll;
const int MN = 21, MOD=1e9+7;
ll lcm (ll a, ll b) {return a*b/__gcd(a,b);}
ll multiplyMod(ll a, ll b) { return (a % MOD * b % MOD) % MOD; }
ll addMod(ll a, ll b) { return (a % MOD + b % MOD) % MOD; }
ll subMod(ll a, ll b) { return (a % MOD - b % MOD) % MOD; }
ll fpow(ll b, ll exp, ll mod){if(exp == 0) return 1;ll t = fpow(b,exp/2,mod);if(exp&1) return t*t%mod*b%mod;return t*t%mod;}
ll divmod(ll i, ll j, ll mod){i%=mod,j%=mod;return i*fpow(j,mod-2,mod)%mod;}
//remember to pop from your queues idot
int dist[MN][MN][MN][MN];
int grid[MN][MN];
int h, w;
char temp;
vpii dirs;
void traverse(int sx, int sy) {
    queue<pii> q;
    q.push({sx, sy});
    dist[sx][sy][sx][sy] = 0;
    while (!q.empty()) {
        int x = q.front().f, y = q.front().s;
        q.pop();
        for (pii moves : dirs) {
            int a = moves.f, b = moves.s;
            int nx = a + x, ny = y + b;
            if (nx > h || nx == 0 || ny > w || ny == 0 || grid[nx][ny]) {
                continue;
            }
            if (dist[sx][sy][x][y] + 1 < dist[sx][sy][nx][ny]) {
                dist[sx][sy][nx][ny] = 1 + dist[sx][sy][x][y];
                q.push({nx, ny});
            }
        }
    }
}
int main() {
    ios_base::sync_with_stdio(0), cin.tie(0), cout.tie(0);
    cin >> h >> w;
    dirs.pb({1, 0}); dirs.pb({0, 1}); dirs.pb({-1, 0}); dirs.pb({0, -1});
    for (int i = 1; i<=h;i++) {
        for (int j = 1; j<=w;j++) {
            cin >> temp;
            grid[i][j] = (temp == '#');
        }
    }
    for (int i = 1; i<=h;i++) {
        for (int j = 1; j<=w;j++) {
            for (int k = 1; k<=h;k++) {
                for (int l = 1; l<=w;l++) {
                    dist[i][j][k][l] = INT_MAX;
                }
            }
        }
    }
    for (int i = 1; i<=h;i++) {
        for (int j = 1; j <= w; j++) {
            if (grid[i][j]) { continue; }
            traverse(i, j);
        }
    }
    int res = 0;
    for (int i = 1; i<=h;i++) {
        for (int j = 1; j<=w;j++) {
            for (int k = 1; k<=h;k++) {
                for (int l = 1; l<=h;l++) {
                    if (dist[i][j][k][l] == INT_MAX) {
                        continue;
                    }
                    res = max(res, dist[i][j][k][l]);
                }
            }
        }
    }
    cout << res << "\n";

    return 0;
}
//lol