#include <iostream>
#include <vector>
#include <algorithm>
#include <stack>
#include <queue>
#include <set>
#include <map>
#include <string>
#include <cstdio>
#include <cstdlib>
#include <string>
#include <cstring>
#include <cmath>
#include <climits>
#include <ctime>
#include <fstream>
#include <functional>
#include <unordered_map>
#include <unordered_set>
#define MAGIC cin.tie(NULL); ios_base::sync_with_stdio(false)
#define endl '\n'
//#define ll long long
#define mod (1000000007)
//#define NCONS 100001
//#define NCONS 100001
//#define NCONS 1001
//#define NCONS 101
//#define MCONS 2001
//#define LIMIT 1000000000
#define TRUE 1
#define FALSE 0
#define toRadian(degree) ((degree) * (M_PI / 180.))
#define toDegree(radian) ((radian) * (180. / M_PI))
#define int long long
//#define double long double
using namespace std;
struct Point{int x; int y;};
struct PPoint{Point x; Point y;};
typedef long long ll;

int gcd(int a, int b) { if(a < b) swap(a, b); if(b <= 0) return a; return gcd(b, a % b); }

#define YYYY cout << "YES" << endl
#define NNNN cout << "NO" << endl
#define yyyy cout << "Yes" << endl
#define nnnn cout << "No" << endl
int dx[]{0, 1, 0, -1};
int dy[]{1, 0, -1, 0};

vector<string> grid;
int H, W;
int dist[20][20][20][20];

int32_t main()
{
    MAGIC;
    cin >> H >> W;
    for(int i = 0; i < H; i++)
    {
        string s; cin >> s; grid.push_back(s);
    }
    
    for(int i = 0; i < H; i++)
    {
        for(int j = 0; j < W; j++)
        {
            for(int k = 0; k < H; k++)
            {
                for(int m = 0; m < W; m++)
                {
                    dist[i][j][k][m] = INT_MAX;
                }
            }
        }
    }
    
    for(int i = 0; i < H; i++)
    {
        for(int j = 0; j < W; j++)
        {
            dist[i][j][i][j] = 0;
        }
    }
    
    // setting the dist
    for(int i1 = 0; i1 < H; i1++)
    {
        for(int i2 = 0; i2 < W; i2++)
        {
            if(grid[i1][i2] == '#') continue;
            for(int k = 0; k < 4; k++)
            {
                int nx = i1 + dx[k];
                int ny = i2 + dy[k];
                if(min(nx, ny) < 0 || nx >= H || ny >= W) continue;
                if(grid[nx][ny] == '#') continue;
                dist[i1][i2][nx][ny] = 1;
            }
        }
    }
    
    
    
    
    for(int k1 = 0; k1 < H; k1++)
    {
        for(int k2 = 0; k2 < W; k2++)
        {
            for(int i1 = 0; i1 < H; i1++)
            {
                for(int i2 = 0; i2 < W; i2++)
                {
                    for(int j1 = 0; j1 < H; j1++)
                    {
                        for(int j2 = 0; j2 < W; j2++)
                        {
                            if(dist[i1][i2][j1][j2] > dist[i1][i2][k1][k2] + dist[k1][k2][j1][j2])
                            {
                                dist[i1][i2][j1][j2] = dist[i1][i2][k1][k2] + dist[k1][k2][j1][j2];
                            }
                        }
                    }
                }
            }
        }
    }
    
    int ret = 0;
    
    for(int i1 = 0; i1 < H; i1++)
    {
        for(int i2 = 0; i2 < W; i2++)
        {
            for(int j1 = 0; j1 < H; j1++)
            {
                for(int j2 = 0; j2 < W; j2++)
                {
                    if(dist[i1][i2][j1][j2] == INT_MAX) continue;
                    ret = max(ret, dist[i1][i2][j1][j2]);
                }
            }
        }
    }
    
    
    cout << ret << endl;
    return 0;
}



Measured memory_bytes: 1536