
fun main(args:Array<String>) {
    val (h,w) = readLine()!!.split(" ").map { it.toInt() }
    Pos.h = h
    Pos.w = w
    val map = (1..h).map { readLine()!! }
    val step = (1..h*w).map { (1..h*w).map { h*w+1 }.toMutableList() }
    val index = (0 until h*w).map { Pos(it/w, it%w) }
    for(i in (0 until  h*w)) {
        for(j in (0 until h*w)) {
            if(map[index[j].r][index[j].c] == '#') {
                continue
            }
            for(k in (0 until h*w)) {
                if(map[index[k].r][index[k].c] == '#') {
                    continue
                }
                if(j == k) {
                    step[j][k] = 0
                    continue
                }
                if(index[j].isNear(index[k])) {
                    step[j][k] = 1
                    continue
                }
                if(map[index[i].r][index[i].c] == '#') {
                    continue
                }
                if(step[j][k] > step[j][i] + step[i][k]) {
                    step[j][k] = step[j][i] + step[i][k]
                }
            }
        }
    }
    val ans =  step.map { it.filter { it != h*w+1 }.max()?:0 }.max() ?:0
    println(ans)
}

class Pos(val r:Int, val c:Int) {
    fun getIndex():Int {
        return r*w+c
    }
    fun isSame(target: Pos):Boolean {
        return r == target.r && c == target.c
    }
    fun isNear(target:Pos):Boolean {
        if(isSame(target)) {
            return false
        }
        if(r ==target.r && Math.abs(c-target.c) == 1) {
            return true
        }
        if(c == target.c && Math.abs(r-target.r) == 1) {
            return true
        }
        return false
    }
    companion object {
        var h:Int = -1
        var w:Int = -1
    }
}