#include <bits/stdc++.h>
using namespace std;
#define ll long long
#define pb push_back
#define pf push_front
#define ff first
#define ss second
#define mkp make_pair
#define pii pair<int, int>
#define vi vector<int>
#define all(x) x.begin(), x.end()
#define sz(x) (int)x.size()
#define nmbr(c) (int)(c-'0')
#define ltr(c) (int)(c-'a')
#define INF 1e18+5
#define mod 10000007
#define fast() ios_base::sync_with_stdio(0);cin.tie(0);cout.tie(0);
template <typename T> T max(T a, T b, T c){ return max(a, max(b, c));}
template <typename T> T min(T a, T b, T c){ return min(a, min(b, c));}
int lcm(int a,int b){return (a*b)/__gcd(a,b);}
bool isPowerOfTwo(int x){return (x && !(x & (x - 1)));}





/*-------------------------------------debug--------------------------------------------------------*/
#define bug(args...) { string _s = #args; replace(_s.begin(), _s.end(), ',', ' '); stringstream _ss(_s); istream_iterator<string> _it(_ss); err(_it, args); }
void err(istream_iterator<string> it) {cout << endl ;}
template<typename T, typename... Args>void err(istream_iterator<string> it, T a, Args... args) {cerr << *it << " = " << a << ' ' ;err(++it, args...);}
template <typename T>ostream& operator<<(ostream& os, const vector<T>& v){os << "[";for (int i = 0; i < v.size(); ++i) {os << v[i];if (i != v.size() - 1)os << ", ";}os << "]\n";return os;}
template <typename T>ostream& operator<<(ostream& os, const set<T>& v){os << "[";for (auto it : v) {os << it;if (it != *v.rbegin())os << ", ";}os << "]\n";return os;}
template <typename T, typename S>ostream& operator<<(ostream& os, const unordered_map<T, S>& v){for (auto it : v)os << it.first << " : "<< it.second << "\n";return os;}
template <typename T, typename S>ostream& operator<<(ostream& os, const pair<T, S>& v){os << "(";os << v.first << ", "<< v.second << ")";return os;}
long long powr(long long a, long long b) {a%=mod;long long res = 1;while (b > 0) {if (b & 1)res = res * a%mod;a = a * a%mod;b >>= 1;}return res;}
/*---------------------------------------------------------------------------------------------------*/


char adj[21][21];
vector<pair<int,int>>v;
bool visited[21][21];
int level[21][21],r,c;
int fx[]={0,1,-1,0};
int fy[]={1,0,0,-1};

int bfs(pair<int,int>source){

    int x=source.ff,y=source.ss;

    //visited[x][y]=1;

    level[x][y]=1;

    queue<pair<int,int>>q;

    q.push(mkp(x,y));

    int Max(0);

    while(!q.empty()){

    pii top=q.front();

    q.pop();

    x=top.ff,y=top.ss;


     if(!visited[x][y])
    for(int i=0;i<4;i++){

        int x1=x+fx[i],y1=y+fy[i];

        if( x1>=0&&x1<r && y1>=0&&y1<c && adj[x1][y1]=='.'&&visited[x1][y1]==0){

        visited[x][y]=1;

        level[x1][y1]=level[x][y]+1;

        Max=max(level[x1][y1]-1,Max);

        q.push(mkp(x1,y1));

        }
    }
    }
    return Max;
}





int main(){
    fast()

    cin>>r>>c;

    for(int i=0;i<r;i++){
        cin>>adj[i];
    }



    for(int i=0;i<r;i++)
    for(int j=0;j<c;j++){

        if(adj[i][j]=='.'){

            v.push_back(mkp(i,j));
        }
    }

    int mx=0;

    while(!v.empty()){

        memset(visited,false,sizeof visited);

        memset(level,0,sizeof level);
        //bug(v.back(),bfs(v.back()))


       mx=max(bfs(v.back()),mx);

       v.pop_back();
    }

    cout<<mx<<endl;



}






Measured memory_bytes: 256