#include <bits/stdc++.h>
using namespace std;
#define fast ios::sync_with_stdio(false); cin.tie(0); cout.tie(0)
#define ll long long int
#define nl cout << endl
#define pb push_back
#define ff first
#define ss second
#define all(ar) ar.begin(), ar.end()
#define Sort(x) sort(all(x))
#define print_vector(my_vector_name) for(int i=0; i<my_vector_name.size(); i++) cout << my_vector_name[i] << " ";nl
//debugger
#define trace1(x)                cerr << #x << ": " << x << endl;
#define trace2(x, y)             cerr << #x << ": " << x << " | " << #y << ": " << y << endl;
#define trace3(x, y, z)          cerr << #x << ": " << x << " | " << #y << ": " << y << " | " << #z << ": " << z << endl;
#define trace4(a, b, c, d)       cerr << #a << ": " << a << " | " << #b << ": " << b << " | " << #c << ": " << c << " | " << #d << ": " << d << endl;
#define trace5(a, b, c, d, e)    cerr << #a << ": " << a << " | " << #b << ": " << b << " | " << #c << ": " << c << " | " << #d << ": " << d << " | " << #e << ": " << e << endl;
#define trace6(a, b, c, d, e, f) cerr << #a << ": " << a << " | " << #b << ": " << b << " | " << #c << ": " << c << " | " << #d << ": " << d << " | " << #e << ": " << e << " | " << #f << ": " << f << endl;

#define hang while (1)

int main3() {
	fast;
	int n,m;
	cin >> n >> m;
	string ac="AC",wa="WA";
	set<int> done;
	int cnt_ac=0,cnt_wa=0;
	for (int i=0; i<m; i++) {
		int id;
		string judge;
		cin >> id >> judge;
		if (done.find(id)==done.end()) {
			if (judge==wa) {
				cnt_wa++;
			} else {
				cnt_ac++;
				done.insert(id);
			}
		}
	}
	cout << cnt_ac << " " << cnt_wa;nl;
	return 0;
}

int run_dijkstra(vector<string> s, int i, int j) {
	int n=s.size();
	int m=s[0].size();
	vector<vector<int> > dist(n,vector<int> (m,1e9));
	dist[i][j]=0;
	queue<pair<int,int> > q;
	q.push({i,j});
	while (q.size()) {
		pair<int,int> p=q.front();
		int a=p.ff,b=p.ss;
		q.pop();
		if (s[a][b]=='#') {
			continue;
		}
		if (a+1<n and dist[a+1][b]>dist[a][b]+1) {
			dist[a+1][b]=dist[a][b]+1;
			q.push({a+1,b});
		}
		if (a-1>=0 and dist[a-1][b]>dist[a][b]+1) {
			dist[a-1][b]=dist[a][b]+1;
			q.push({a-1,b});
		}
		if (b+1<m and dist[a][b+1]>dist[a][b]+1) {
			dist[a][b+1]=dist[a][b]+1;
			q.push({a,b+1});
		}
		if (b-1>=0 and dist[a][b-1]>dist[a][b]+1) {
			dist[a][b-1]=dist[a][b]+1;
			q.push({a,b-1});
		}
	}
	int ans=0;
	for (int x=0; x<n; x++) {
		for (int y=0; y<m; y++) {
			if (s[x][y]=='#') {
				continue;
			}
			ans=max(ans,dist[x][y]);
		}
	}
	return ans;
}

int main() {
	fast;
	int n,m;
	cin >> n >> m;
	vector<string> s(n);
	for (int i=0; i<n; i++) {
		cin >> s[i];
	}
	int ans=0;
	for (int i=0; i<n; i++) {
		for (int j=0; j<m; j++) {
			if (s[i][j]!='#') {
				ans = max(ans,run_dijkstra(s,i,j));
			}
		}
	}
	cout << ans;
	return 0;
}

//notes
/*
 value of INT_MAX and INT_MIN is fixed and they are
 INT_MAX = 2147483647
 INT_MIN = -2147483648
 use these format of input when number of inputs not provided
 *while(scanf("%lld",&n)!=EOF)
 *while using getline(cin,s) for taking input of a string which is 
 having white space characters just write cin>>ws; before geline(cin,s)
 to make it work properly
*/

/*
 use 2-D vector for representing the pair<int,pair<int,int> > kind of things
*/

Measured memory_bytes: 256