from sys import stdin
import numpy as np
from scipy.ndimage.filters import minimum_filter, maximum_filter

def init_maze(maze, H, W, start, goal):
    cost = np.zeros((H, W), dtype=int) + 999
    done = np.zeros((H, W), dtype=bool)
    barrier = np.zeros((H, W), dtype=bool)
    for i in range(H):
        for j in range(W):
            if (i, j) == start:
                # start = (i, j)
                cost[i, j] = 0
                done[i, j] = True
            if (i, j) == goal:
                pass
                # goal = (i, j)
            if maze[i][j] == '#':
                barrier[i,j] = True
    return cost, done, barrier

def bnf(maze, cost, done, barrier, goal, g):
    for i in range(1, 999):
        done_next = maximum_filter(done, footprint=g) * ~done

        cost_next = minimum_filter(cost, footprint=g) * done_next
        cost_next[done_next] += 1

        cost[done_next] = cost_next[done_next]
        cost[barrier] = 999

        done[done_next] = done_next[done_next]
        done[barrier] = False

        if done[goal[0], goal[1]] == True:
            return max(cost_next[done_next])
            break
    return 0


if __name__ == '__main__':
    H, W = [ int(x) for x in stdin.readline().rstrip().split() ]
    maze = []
    for i in range(H):
        maze.append(stdin.readline().rstrip())

    index = []
    for i in range(H):
        for j in range(W):
            if maze[i][j] == '.':
                index.append((i, j))

    g = np.array([
        [0,1,0],
        [1,1,1],
        [0,1,0]
    ])

    costs = []
    for idx_start in index:
        start = idx_start
        for idx_goal in index:
            goal = idx_goal
            cost, done, barrier = init_maze(maze, H, W, start, goal)
            cost, done, barrier = init_maze(maze, H, W, start, goal)
            costs.append(bnf(maze, cost, done, barrier, goal, g))
    print(max(costs))
