#pragma comment (linker, "/STACK:256000000")
#define  _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <algorithm>
#include <utility>
#include <functional>
#include <cstring>
#include <queue>
#include <stack>
#include <math.h>
#include <iterator>
#include <vector>
#include <string>
#include <set>
#include <math.h>
#include <iostream>
#include <random>
#include<map>
#include <iomanip>
#include <time.h>
#include <stdlib.h>
#include <list>
#include <typeinfo>
#include <list>
#include <set>
#include <cassert>
#include<fstream>
#include <unordered_map>
#include <unordered_set>
#include <cstdlib>
#include <complex>
#include <cctype>
#include <bitset>

using namespace std;
typedef string::const_iterator State;
const long double Ma_PI = 3.1415926535897932384626433832795028841971L;
#define eps 1e-7
#define LONG_INF 2000000000000000000LL
#define GOLD 1.61803398874989484820458
#define MAX_MOD 1000000007LL
#define GYAKU 500000004LL

#define MOD 998244353LL
#define seg_size 262144*2
#define pb push_back
#define mp make_pair
typedef long long ll;
#define REP(a,b) for(long long a = 0;a < b;++a)
#define ALL(x) (x).begin(),(x).end()
void init() {
    iostream::sync_with_stdio(false);
    cout << fixed << setprecision(20);
}
unsigned long xor128() {
    static unsigned long x = 123456789, y = 362436069, z = 521288629, w = 88675123;
    unsigned long t = (x ^ (x << 11));
    x = y; y = z; z = w;
    return (w = (w ^ (w >> 19)) ^ (t ^ (t >> 8)));
}
typedef struct BigInt{
    string s = "0";
    BigInt operator +(BigInt obj) {
        string c;
        while (max(obj.s.length(), this->s.length()) + 1 > c.length()) {
            c.pb('0');
        }
        for (int q = 0; q < obj.s.length(); ++q) {
            c[c.length() - 1 - q] = obj.s[obj.s.length() - q - 1];
        }
        for (int q = 0; q < this->s.length(); ++q) {
            c[c.length() - 1 - q] += this->s[this->s.length() - 1 - q] - '0';
            if (c[c.length() - 1 - q] > '9') {
                c[c.length() - 2 - q]++;
                c[c.length() - 1 - q] -= 10;
            }
        }
        if (c.front() == '0') {
            c.erase(c.begin());
        }
        return BigInt{ c };
    }
    BigInt operator *(BigInt obj) {
        BigInt ans;
        for (int i = this->s.length() - 1; i >= 0; --i) {
            REP(q, this -> s[i] - '0') {
                ans = ans + obj;
            }
            obj.s.pb('0');
        }
        return ans;
    }
}BigInt;

int grid[20][20];
int tmp[20][20];
void solve() {
    int h, w;
    cin >> h >> w;
    REP(i, h) {
        string s;
        cin >> s;
        REP(q, s.length()) {
            if (s[q] == '#') {
                grid[i][q] = 1;
            }
        }
    }
    int ans = 0;
    REP(i, h) {
        REP(q, w) {
            if (grid[i][q] == 1) continue;
            REP(j, h) {
                REP(t, w) {
                    tmp[j][t] = 1e9;
                }
            }
            tmp[i][q] = 0;
            queue<pair<int, int>> next;
            next.push(mp(i, q));
            int xe[4] = { 1,-1,0,0 };
            while (next.empty() == false) {
                pair<int, int> now = next.front();
                next.pop();
                ans = max(ans, tmp[now.first][now.second]);
                REP(j, 4) {
                    int now_x = now.first + xe[j];
                    int now_y = now.second + xe[3 - j];
                    if (now_x >= 0 && now_x < h && now_y >= 0 && now_y < w) {
                        if (grid[now_x][now_y] == 0&&tmp[now_x][now_y] > tmp[now.first][now.second] + 1) {
                            tmp[now_x][now_y] = tmp[now.first][now.second] + 1;
                            next.push(mp(now_x, now_y));
                        }
                    }
                }
            }
        }
    }
    cout << ans << endl;
}

int main() {
    init();
    solve();
}

Measured memory_bytes: 256