#include<stdio.h>
#include<iostream>
#include <cstdio>
#include <cstdlib>
#include <algorithm>
#include <cmath>
#include <vector>
#include <set>
#include <map>
#include <unordered_set>
#include <unordered_map>
#include <queue>
#include <ctime>
#include <cassert>
#include <complex>
#include <string>
#include <cstring>
#include <chrono>
#include <random>
#include <queue>
#include <bitset>
#include<bits/stdc++.h>
using namespace std;
#define ll          long long
#define pb          push_back
#define pii         pair<long,long>
#define vi          vector<long>
#define vii         vector<pii>
#define mi          map<long,long>
#define mii         map<pii,long>
#define all(a)      (a).begin(),(a).end()
#define x           first
#define y           second
#define sz(x)       (int)x.size()
#define endl        '\n'
#define hell        1000000007
#define rep(i,a,b)  for(int i=a;i<b;i++)
#define lbnd        lower_bound
#define ubnd        upper_bound
#define bs          binary_search
#define fIO ios_base::sync_with_stdio(false); cin.tie(NULL); cout.tie(NULL);

ll sub(ll a, ll b){return (a-b+hell)%hell;}
ll add(ll a, ll b){return (a+b)%hell;}
ll mul(ll a, ll b){return (a*b)%hell;}
int n,m;
struct Point 
{ 
    int x; 
    int y; 
}; 
  
// A Data Structure for queue used in BFS 
struct queueNode 
{ 
    Point pt;  // The cordinates of a cell 
    int dist;  // cell's distance of from the source 
}; 
  
// check whether given cell (row, col) is a valid 
// cell or not. 
bool isValid(int row, int col) 
{ 
    // return true if row number and column number 
    // is in range 
    return (row >= 0) && (row < n) && 
           (col >= 0) && (col <m); 
} 
  
// These arrays are used to get row and column 
// numbers of 4 neighbours of a given cell 
int rowNum[] = {-1, 0, 0, 1}; 
int colNum[] = {0, -1, 1, 0}; 
  
// function to find the shortest path between 
// a given source cell to a destination cell. 
int BFS(int a[][21], Point src, Point dest) 
{ 
    // check source and destination cell 
    // of the matrix have value 1 
    if (!a[src.x][src.y] || !a[dest.x][dest.y]) 
        return -1; 
  
    bool visited[n][m]; 
    memset(visited, false, sizeof visited); 
      
    // Mark the source cell as visited 
    visited[src.x][src.y] = true; 
  
    // Create a queue for BFS 
    queue<queueNode> q; 
      
    // Distance of source cell is 0 
    queueNode s = {src, 0}; 
    q.push(s);  // Enqueue source cell 
  
    // Do a BFS starting from source cell 
    while (!q.empty()) 
    { 
        queueNode curr = q.front(); 
        Point pt = curr.pt; 
  
        // If we have reached the destination cell, 
        // we are done 
        if (pt.x == dest.x && pt.y == dest.y) 
            return curr.dist; 
  
        // Otherwise dequeue the front cell in the queue 
        // and enqueue its adjacent cells 
        q.pop(); 
  
        for (int i = 0; i < 4; i++) 
        { 
            int row = pt.x + rowNum[i]; 
            int col = pt.y + colNum[i]; 
              
            // if adjacent cell is valid, has path and 
            // not visited yet, enqueue it. 
            if (isValid(row, col) && a[row][col] &&  
               !visited[row][col]) 
            { 
                // mark cell as visited and enqueue it 
                visited[row][col] = true; 
                queueNode Adjcell = { {row, col}, 
                                      curr.dist + 1 }; 
                q.push(Adjcell); 
            } 
        } 
    } 
  
    // Return -1 if destination cannot be reached 
    return -1; 
} 
  
// Driver program to test above function 



int main()
{
fIO;


/*#ifndef ONLINE_JUDGE
freopen("input.txt","r",stdin);
freopen("output.txt","w",stdout);
#endif*/


long long t=1;
//cin >> t;
while(t--){
   cin>>n>>m;
   char c;
   int a[21][21];
   rep(i,0,n){
       rep(j,0,m){
           cin>>c;
           if(c=='.')a[i][j]=1;
           else a[i][j]=0;
       }
   }
   
    Point source = {0, 0}; 
    Point dest = {n-1, m-1}; 
  
    int dist = BFS(a, source, dest); 
  
   int ans=0; 

  rep(i,0,n){
      rep(j,0,m){
         source = {i, j}; 
    rep(k,0,n){
        rep(l,0,m){
            dest={k,l};
             int dist1 = BFS(a, source, dest);
        ans=max(ans,dist1);
        }
    }
    
      }
  }
  
  source = {n-1, 0}; 
    dest = {0,  m-1}; 
    int dist1 = BFS(a, source, dest); 
    cout <<ans;
    return 0; 
}
	
}

Measured memory_bytes: 256