#include <bits/stdc++.h>
void read_from_cin() {}
template <typename T, typename... Ts>
void read_from_cin(T& value, Ts&... args) {
  std::cin >> value;
  read_from_cin(args...);
}
template <typename T>
void write_to_cout(const T& value) {
  std::cout << value << std::endl;
}
template <typename T, typename... Ts>
void write_to_cout(const T& value, const Ts&... args) {
  std::cout << value << ' ';
  write_to_cout(args...);
}
using ll = long long;
using namespace std;
int main() {
  int H, W;
  read_from_cin(H, W);
  ;
  vector<string> m(H);
  int sr, sc;
  for (int i = 0; i < (int)(H); ++i) {
    cin >> m[i];
    for (int j = 0; j < (int)(W); ++j)
      if (m[i][j] == '.') {
        sr = i, sc = j;
      }
  }
  queue<tuple<int, int, int>> que;
  que.push(make_tuple(sr, sc, 0));
  set<pair<int, int>> seen;
  seen.insert({sr, sc});
  int gr, gc;
  while (!que.empty()) {
    int cr, cc, dist;
    tie(cr, cc, dist) = que.front();
    que.pop();
    gr = cr, gc = cc;
    ;
    for (int d = 0; d < (int)(4); ++d) {
      int dr[] = {0, 0, 1, -1};
      int dc[] = {1, -1, 0, 0};
      int nr = cr + dr[d];
      int nc = cc + dc[d];
      if (nr < 0 || H <= nr || nc < 0 || W <= nc || m[nr][nc] != '.') continue;
      if (seen.count({nr, nc})) continue;
      seen.insert({nr, nc});
      que.push(make_tuple(nr, nc, dist + 1));
    }
  }
  int ans = 0;
  que.push(make_tuple(gr, gc, 0));
  seen.clear();
  seen.insert({gr, gc});
  while (!que.empty()) {
    int cr, cc, dist;
    tie(cr, cc, dist) = que.front();
    que.pop();
    ans = dist;
    for (int d = 0; d < (int)(4); ++d) {
      int dr[] = {0, 0, 1, -1};
      int dc[] = {1, -1, 0, 0};
      int nr = cr + dr[d];
      int nc = cc + dc[d];
      if (nr < 0 || H <= nr || nc < 0 || W <= nc || m[nr][nc] != '.') continue;
      if (seen.count({nr, nc})) continue;
      seen.insert({nr, nc});
      que.push(make_tuple(nr, nc, dist + 1));
    }
  }
  write_to_cout(ans);
  ;
}
