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)).new
queue << start
visited = Set(Tuple(Int32, Int32)).new
visited << start
last_visit = start
until queue.empty?
  x, y = queue.shift
  last_visit = {x, y}
  if ok(h, w, cells, visited, x - 1, y)
    queue << {x - 1, y}
    visited << {x - 1, y}
  end
  if ok(h, w, cells, visited, x + 1, y)
    queue << {x + 1, y}
    visited << {x + 1, y}
  end
  if ok(h, w, cells, visited, x, y - 1)
    queue << {x, y - 1}
    visited << {x, y - 1}
  end
  if ok(h, w, cells, visited, x, y + 1)
    queue << {x, y + 1}
    visited << {x, y + 1}
  end
end

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

p last_depth
