#include <bits/stdc++.h>
using namespace std;
using lint = long long int;
constexpr int MOD = 1000000007;
constexpr int INF = 2147483647;
int main() {
  int H, W;
  cin >> H >> W;
  vector<vector<bool>> maze(H + 2, vector<bool>(W + 2, false));
  for (int i = (0), i_end_ = (H); i < i_end_; i++) {
    string S;
    cin >> S;
    for (int j = (0), j_end_ = (W); j < j_end_; j++) {
      if (S[j] == '.') {
        maze[i + 1][j + 1] = true;
      }
    }
  }
  int max = 0;
  for (int i = (0), i_end_ = (H); i < i_end_; i++) {
    for (int j = (0), j_end_ = (W); j < j_end_; j++) {
      if (!maze[i + 1][j + 1]) continue;
      deque<tuple<int, int, int>> q;
      vector<vector<bool>> used(H + 2, vector<bool>(W + 2, false));
      q.push_front(make_tuple(i, j, 0));
      used[i + 1][j + 1] = true;
      while (!q.empty()) {
        int ii = get<0>(q.back());
        int jj = get<1>(q.back());
        int nn = get<2>(q.back());
        cout << ii << " " << jj << " " << nn << endl;
        q.pop_back();
        if (nn > max) max = nn;
        if (maze[ii][jj + 1] && !used[ii][jj + 1]) {
          q.push_front(make_tuple(ii - 1, jj, nn + 1));
          used[ii][jj + 1] = true;
        }
        if (maze[ii + 2][jj + 1] && !used[ii + 2][jj + 1]) {
          q.push_front(make_tuple(ii + 1, jj, nn + 1));
          used[ii + 2][jj + 1] = true;
        }
        if (maze[ii + 1][jj] && !used[ii + 1][jj]) {
          q.push_front(make_tuple(ii, jj - 1, nn + 1));
          used[ii + 1][jj] = true;
        }
        if (maze[ii + 1][jj + 2] && !used[ii + 1][jj + 2]) {
          q.push_front(make_tuple(ii, jj + 1, nn + 1));
          used[ii + 1][jj + 2] = true;
        }
      }
    }
  }
  cout << max << endl;
}
