#include<bits/stdc++.h>
//#pragma GCC optimize("Ofast")
//#pragma GCC optimize ("unroll-loops")
//#pragma GCC target("sse,sse2,sse3,ssse3,sse4,popcnt,abm,mmx,avx,tune=native")
//#pragma comment(linker, "/stack:200000000")
using namespace std;
#define F first
#define S second
#define EB emplace_back
#define MP make_pair
#define all(o) (o).begin(), (o).end()
#define mset(m,v) memset(m,v,sizeof(m))
#define fr(i,n) for(lli i=0;i<(n);++i)
#define rep(i,a,b) for(lli i=a;i<=b;++i)
#define per(i,a,b) for(lli i=a;i>=b;i--)
#define remin(a,b) (a=min((a),(b)))
#define remax(a,b) (a=max((a),(b))) 
#define sz(x) (lli)(x).size()
#define endl '\n'
typedef long long lli;        typedef long double ld;
typedef pair<lli,lli> ii;     typedef vector<lli> vi;
typedef vector<ii> vii;       typedef vector<vi> graph;
long long MOD=1000000007;     long double EPS=1e-9;
#ifndef ONLINE_JUDGE
#define debarr(a,n)cerr<<#a<<":";for(int i=0;i<n;i++)cerr<<a[i]<<" ";cerr<<endl;
#define debmat(mat,row,col)cerr<<#mat<<":\n";for(int i=0;i<row;i++){for(int j=0;j<col;j++)cerr<<mat[i][j]<<" ";cerr<<endl;}
#define pr(...)dbs(#__VA_ARGS__,__VA_ARGS__)
template<class S,class T>ostream &operator<<(ostream &os,const pair<S,T> &p){return os<<"("<<p.first<<","<<p.second<<")";}
template<class T>ostream &operator<<(ostream &os,const vector<T> &p){os<<"[";for(auto&it:p)os<<it<<" ";return os<<"]";}
template<class T>ostream &operator<<(ostream &os,const set<T>&p){os<<"[";for(auto&it:p)os<<it<<" ";return os<<"]";}
template<class T>ostream &operator<<(ostream &os,const multiset<T>&p){os<<"[";for(auto&it:p)os<<it<<" ";return os<<"]";}
template<class S,class T>ostream &operator<<(ostream &os,const map<S,T>&p){os<<"[";for(auto&it:p)os<<it<<" ";return os<<"]";}
template<class T>void dbs(string str,T t){cerr<<str<<":"<<t<<"\n";}
template<class T,class...S>void dbs(string str,T t,S... s){int idx=str.find(',');cerr<<str.substr(0,idx)<<":"<<t<<",";dbs(str.substr(idx+1),s...);}
#else
#define pr(...){}
#define debarr(a,n){}
#define debmat(mat,row,col){}
#endif
lli binpow(lli b,lli p,lli mod){lli ans=1;b%=mod;for(;p;p>>=1){if(p&1)ans=ans*b%mod;b=b*b%mod;}return ans;}

void pre(){

}

int n,m;
vector<string> arr;

namespace IMPLICIT_BFS{
    int dx[]={1,0,-1,0};
    int dy[]={0,1,0,-1};
    bool isvalid(int i,int j){
        if(i<n&&i>=0&&j<m&&j>=0&&arr[i][j]!='#')return 1;
        else return 0;
    }
    #define MAXN 202
    int dis[MAXN][MAXN];
    queue<ii> st;
    void init(vector<ii> beg){
        fr(i,MAXN)fr(j,MAXN)dis[i][j]=MOD;
        for(auto v:beg){
            dis[v.F][v.S]=0;
            st.push(v);
        }
    }
    ii last;
    void bfs(){
        while(!st.empty()){    
            last=st.front();st.pop();
            lli x=last.F;lli y=last.S;
            for(int i=0;i<4;i++){
                if(isvalid(x+dx[i],y+dy[i])&&dis[x+dx[i]][y+dy[i]] > dis[x][y]+1){
                    dis[x+dx[i]][y+dy[i]]=dis[x][y]+1;
                    st.push(MP(x+dx[i],y+dy[i]));
                }
            }
        }
    }
}using namespace IMPLICIT_BFS;

int best[22][22];

void solve(){
    cin>>n>>m;
    arr.resize(n);
    fr(i,n)cin>>arr[i];
    fr(i,n){
        fr(j,m){
            if(arr[i][j]=='.'){
                vii temp;
                temp.EB(MP(i,j));
                init(temp);
                bfs();
                fr(x,n)fr(y,m){
                    if(dis[x][y]!=MOD)remax(best[x][y],dis[x][y]);
                }
            }
        }
    }
    int ans=0;
    fr(i,n)fr(j,m){
        remax(ans,best[i][j]);
    }
    cout<<ans<<endl;
}

signed main(){
    ios_base::sync_with_stdio(false);cin.tie(0);cout.tie(0);
    //freopen("in.txt","r",stdin);
    //freopen("out.txt","w",stdout);
    //cout<<fixed<<setprecision(15);
    //clock_t begin = clock();
    pre();lli _t=1;//cin>>_t;
    for(lli i=1;i<=_t;i++){
        //cout<<"Case #"<<i<<": ";
        solve();
    }
    // clock_t end = clock();double elapsed_secs = double(end - begin) / CLOCKS_PER_SEC;cerr << elapsed_secs;
}

Measured memory_bytes: 384