#include <bits/stdc++.h>
using namespace std;
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
#define pb push_back
#define mp make_pair
#define all(a)      (a).begin(),(a).end()
#define debug_array(a,n) for (ll bccc=(0); bccc<(n); bccc++) cout<<a[bccc]<<" "<<"\n"
#define debug_vector(a) for(ll bccc=(0); bccc<(a.size());bccc++) cout<<a[bccc]<<" "<<"\n"
#define F           first
#define S           second
#define debug_set(s) for(auto p:s) cout<<p<<" "
#define debug_map(m) for(auto p:m) cout<<p.F<<" "<<p.S<<"\n"
#define trace(x) cerr<<#x<<": "<<x<<" "<<endl;
typedef long long ll;
using namespace __gnu_pbds;
typedef tree<pair<ll,ll>,null_type,less<pair<ll,ll> >,rb_tree_tag,tree_order_statistics_node_update> ordered_multiset;
/* ll t = 0;
ordered_multiset me;
...
me.insert({x, t++});
me.erase(me.lower_bound({x, 0}));
cout << me.order_of_key({x, 0}) << "\n";

///////////   t is insertion time
*/
//#pragma GCC optimize("Ofast")  // works very well
#define ordered_set tree<ll, null_type,less<ll>, rb_tree_tag,tree_order_statistics_node_update>
mt19937 rng(chrono::high_resolution_clock::now().time_since_epoch().count());
typedef long double lld;
lld pi=3.14159265358;
ll powr(ll a,ll b)
{
    ll c=1;
    ll kjk;
    for(kjk=0;kjk<b;kjk++)
        c*=a;
    return c;
}
ll hell=1000000007;
//ll hell=998244353   ;
ll power(ll x, ll y, ll p)
{
    ll res = 1;
    x = x % p;
    while (y > 0)
    {
        if (y & 1)
            res = (res*x) % p;
        y = y>>1;
        x = (x*x) % p;
    }
    return res;
}
//freopen("input.txt", "r", stdin);
//freopen("output.txt", "w", stdout);
// to generate random number , use rng() ... eg cout<<rng();
ll h,w;
string s[20];
int vis[20][20];
ll dis[20][20];
ll dfs(ll i,ll j,ll dep)
{
    vis[i][j]=1;
    dis[i][j]=min(dis[i][j],dep);
    if(i>0 && s[i-1][j]=='.' && dep+1<dis[i-1][j])
        dfs(i-1,j,dep+1);
    if(i<(h-1) && s[i+1][j]=='.' && (dep+1)<dis[i+1][j])
        dfs(i+1,j,dep+1);
    if(j>0 && s[i][j-1]=='.' && (dep+1)<dis[i][j-1])
        dfs(i,j-1,dep+1);
    if(j<(w-1) && s[i][j+1]=='.' && (dep+1)<dis[i][j+1])
        dfs(i,j+1,dep+1);

}
void init()
{
    for(ll pp=0;pp<20;pp++)
    {
        for(ll qq=0;qq<20;qq++)
            dis[pp][qq]=hell;
    }
}
int main()
{
    ios_base::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
    srand(chrono::high_resolution_clock::now().time_since_epoch().count());
    ll i,j;
    cin>>h>>w;
    for(i=0;i<h;i++)
        cin>>s[i];
    ll m=0;
    /*init();
    dfs(0,0,0);
    for(ll p=0;p<h;p++)
                {
                    for(ll q=0;q<w;q++)
                    {
                        if(s[p][q]=='.')
                            m=max(m,(ll)dis[p][q]);
                    }
                }
    for(i=0;i<3;i++)
    {
        for(j=0;j<3;j++)
        {
            cout<<dis[i][j]<<" ";
        }
        cout<<"\n";
    }*/
    for(i=0;i<h;i++)
    {
        for(j=0;j<w;j++)
        {
            if(s[i][j]=='.')
            {
                memset(vis,0,sizeof(vis));
                memset(dis,0,sizeof(dis));
                init();
                dfs(i,j,0);
                for(ll p=0;p<h;p++)
                {
                    for(ll q=0;q<w;q++)
                    {
                        if(s[p][q]=='.')
                            m=max(m,(ll)dis[p][q]);
                    }
                }
            }
        }
    }
    cout<<m;
    return 0;
}


Measured memory_bytes: 256