h, w = read_line.split.map(&.to_i64)
cells = Array(Array(Char)).new
start = {-1, -1}
h.times do |y|
  cells << read_line.chars
  pos = cells.last.index('.')
  if start == {-1, -1} && !pos.nil?
    start = {pos, y.to_i32}
  end
end

def ok(h, w, cells, visited, x, y)
  x >= 0 && y >= 0 && x < w && y < h && !visited.includes?({x, y}) && cells[y][x] == '.'
end

queue = Deque(Tuple(Int32, Int32, Int32)).new
queue << {start[0], start[1], 0}
visited = Set(Tuple(Int32, Int32)).new
visited << start
max_depth = 0
max_depth_points = [] of Tuple(Int32, Int32)

until queue.empty?
  x, y, depth = queue.shift
  if max_depth == depth
    max_depth_points << {x, y}
  else
    max_depth = depth
    max_depth_points = [{x, y}]
  end
  if ok(h, w, cells, visited, x - 1, y)
    queue << {x - 1, y, depth + 1}
    visited << {x - 1, y}
  end
  if ok(h, w, cells, visited, x + 1, y)
    queue << {x + 1, y, depth + 1}
    visited << {x + 1, y}
  end
  if ok(h, w, cells, visited, x, y - 1)
    queue << {x, y - 1, depth + 1}
    visited << {x, y - 1}
  end
  if ok(h, w, cells, visited, x, y + 1)
    queue << {x, y + 1, depth + 1}
    visited << {x, y + 1}
  end
end

ans = 0_i64

max_depth_points.each do |last_visit|
  queue = Deque(Tuple(Int32, Int32, Int32)).new
  queue << {last_visit[0], last_visit[1], 0}
  visited = Set(Tuple(Int32, Int32)).new
  visited << last_visit
  last_depth = 0
  until queue.empty?
    x, y, depth = queue.shift
    last_depth = depth
    if ok(h, w, cells, visited, x - 1, y)
      queue << {x - 1, y, depth + 1}
      visited << {x - 1, y}
    end
    if ok(h, w, cells, visited, x + 1, y)
      queue << {x + 1, y, depth + 1}
      visited << {x + 1, y}
    end
    if ok(h, w, cells, visited, x, y - 1)
      queue << {x, y - 1, depth + 1}
      visited << {x, y - 1}
    end
    if ok(h, w, cells, visited, x, y + 1)
      queue << {x, y + 1, depth + 1}
      visited << {x, y + 1}
    end
  end
  if ans < last_depth
    ans = last_depth
  end
end

p ans
