#include <bits/stdc++.h>
using namespace std;
template <typename T0, typename T1>
std::ostream& operator<<(std::ostream& os, const map<T0, T1>& v) {
  for (typename map<T0, T1>::const_iterator p = v.begin(); p != v.end(); p++) {
    os << p->first << ": " << p->second << " ";
  }
  return os;
}
template <typename T0, typename T1>
std::ostream& operator<<(std::ostream& os, const pair<T0, T1>& v) {
  os << v.first << ": " << v.second << " ";
  return os;
}
template <typename T>
std::ostream& operator<<(std::ostream& os, const vector<T>& v) {
  for (int i = 0; i < (int)v.size(); i++) {
    os << v[i] << " ";
  }
  return os;
}
template <typename T>
std::ostream& operator<<(std::ostream& os, const set<T>& v) {
  vector<T> tmp(v.begin(), v.end());
  os << tmp;
  return os;
}
template <typename T>
std::ostream& operator<<(std::ostream& os, const deque<T>& v) {
  vector<T> tmp(v.begin(), v.end());
  os << tmp;
  return os;
}
template <typename T>
std::ostream& operator<<(std::ostream& os, const vector<vector<T>>& v) {
  for (int i = 0; i < (int)v.size(); i++) {
    os << v[i] << endl;
  }
  return os;
}
template <typename T>
void maxUpdate(T& a, T b) {
  a = max(a, b);
}
template <typename T>
void minUpdate(T& a, T b) {
  a = min(a, b);
}
vector<string> m;
vector<vector<long long>> P, VIS;
void f(long long sx, long long sy, long long& fx, long long& fy) {
  queue<pair<long long, long long>> q;
  long long H = m.size();
  long long W = m[0].size();
  P = vector<vector<long long>>(H, vector<long long>(W, (1LL << 60)));
  VIS = vector<vector<long long>>(H, vector<long long>(W));
  P[sy][sx] = 0;
  q.push(make_pair(sx, sy));
  while (q.size()) {
    auto xy = q.front();
    q.pop();
    long long x = xy.first;
    long long y = xy.second;
    if (VIS[y][x]) continue;
    VIS[y][x] = 1;
    long long dx[] = {-1, 0, 1, 0};
    long long dy[] = {0, -1, 0, 1};
    for (long long dir = 0, _n = (4); (dir) < (long long)_n; ++dir) {
      long long nx = x + dx[dir];
      long long ny = y + dy[dir];
      if (((0) <= (nx) && (nx) < (W)) && ((0) <= (ny) && (ny) < (H)) &&
          m[ny][nx] == '.' && !VIS[ny][nx]) {
        minUpdate(P[ny][nx], P[y][x] + 1);
        q.push(make_pair(nx, ny));
      }
    }
  }
  fx = 0;
  fy = 0;
  for (long long y = 0, _n = (H); (y) < (long long)_n; ++y)
    for (long long x = 0, _n = (W); (x) < (long long)_n; ++x)
      if (P[fy][fx] == (1LL << 60) ||
          (P[y][x] < (1LL << 60) && P[y][x] > P[fy][fx])) {
        fx = x;
        fy = y;
      }
}
int main() {
  cin.tie(0);
  ios::sync_with_stdio(false);
  long long W, H;
  while (cin >> H >> W) {
    m = vector<string>(H);
    for (long long i = 0, _n = (H); (i) < (long long)_n; ++i) cin >> m[i];
    long long sx, sy, fx, fy;
    for (long long y = 0, _n = (H); (y) < (long long)_n; ++y)
      for (long long x = 0, _n = (W); (x) < (long long)_n; ++x)
        if (m[y][x] == '.') {
          sx = x;
          sy = y;
        }
    f(sx, sy, fx, fy);
    sx = fx;
    sy = fy;
    f(sx, sy, fx, fy);
    long long ans = P[fy][fx] - P[sy][sx];
    cout << ans << endl;
  }
  return 0;
}
