      MODULE intQueueMod
      implicit none
! Module for QUEUE : First in, First out
! reference : プログラミングコンテスト攻略のための
!              アルゴリズムとデータ構造

      integer(16),parameter :: binSize = 10**7
      integer(16),parameter :: precision = 4
      
      type intQueue
        private
        integer(precision) :: bin( 1:binSize ) = 0
        integer(precision) :: head = 1,   tail = 1
        !head : Where the head value is.
        !tail : Where the blank next to tail is.
        contains
        procedure,public,pass :: initialize => intInit
        procedure,public,pass :: isEmpty    => intIsEmpty
        procedure,public,pass :: isFull     => intIsFull
        procedure,public,pass :: enQueue    => intEnQ
        procedure,public,pass :: deQueue    => intDeQ
      end type
      
      contains
!Reset queue. Not nessesary in first time.
      pure subroutine intInit( q )
        implicit none
        class(intQueue),intent(inout) :: q
        
        q%head = 1
        q%tail = 1
      end subroutine intInit
      
!Check status
      pure function intIsEmpty( q ) result( ans )
        implicit none
        class(intQueue),intent(in) :: q
        logical :: ans
        
        ans = q%head==q%tail
      end function intIsEmpty
      
      
      pure function intIsFull( q ) result( ans )
        implicit none
        class(intQueue),intent(in) :: q
        logical :: ans
        
        ans = q%head==mod( q%tail+1,binSize )
      end function intIsFull

!set x to tail
      subroutine intEnQ( q,x )
        implicit none
        class(intQueue)      ,intent(inout) :: q
        integer(precision),intent(in   ) :: x
        
        if( q%isFull() )then
          print*,'Queue is full,Error!';stop
        else
          q%bin(q%tail) = x
          if( q%tail==binSize )then
            q%tail = 1
          else
            q%tail = q%tail + 1
          end if
        end if
      end subroutine intEnQ
      
!get x from head
      impure function intDeQ( q ) result( x )
        implicit none
        class(intQueue),intent(inout) :: q
        integer(precision) :: x
        
        if( q%isEmpty() )then
          print*,'Stack is empty, Error!';stop
        else
          x = q%bin(q%head)
          if( q%head==binSize )then
            q%head = 1
          else
            q%head = q%head + 1
          end if
        end if
      end function intDeQ
      END MODULE intQueueMod
      
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

      PROGRAM mazeMaster
      use intQueueMod
      implicit none
      integer :: h,w,ans=0
      logical,allocatable :: maze(:,:),isVisited(:,:)
      character(20) :: s
      integer :: i,j
      integer,allocatable :: dist(:,:)
      
      
      
      read*,h,w
      allocate( maze(h,w),isVisited(h,w),source=.true. )
      allocate( dist(h,w),source=0 )
      do i = 1,h
        read*,s(1:w)
        do j = 1,w
          if(s(j:j)=='#') maze(i,j)=.false.
        end do
      end do
      
      
      do i = 1,h
        do j = 1,w
          
          if( .not.maze(i,j) )cycle
          call solve( i,j )
          ans = max(ans,maxval(dist))
          
        end do
      end do
      
      print*,ans
      
      
      contains
      subroutine solve( i,j )
        implicit none
        integer,intent(in) :: i,j
        type(intQueue) :: Qh,Qw,Qd
        integer :: nowi,nowj,ii(4),jj(4),iter
        
        isVisited(:,:) = .false.
        dist(:,:) = 0
        call Qh%enQueue(i)
        call Qw%enQueue(j)
        call Qd%enQueue(0)
        
        do while(.true.)
          if( Qh%isEmpty() )return
          
          nowi = Qh%dequeue()
          nowj = Qw%dequeue()
          dist(nowi,nowj) = Qd%dequeue()
          isVisited(nowi,nowj) = .true.
          
          ii = [-1,0,1,0]
          jj = [0,-1,0,1]
          
          
          do iter = 1,4
              if( nowi+ii(iter)<1 .or. h<nowi+ii(iter) .or. &
                  nowj+jj(iter)<1 .or. w<nowj+jj(iter) ) cycle
              if( .not.(maze(nowi+ii(iter),nowj+jj(iter))) ) cycle
              if( isVisited(nowi+ii(iter),nowj+jj(iter)) ) cycle
              
              
              
              call Qh%enQueue( nowi+ii(iter) )
              call Qw%enQueue( nowj+jj(iter) )
              call Qd%enQueue( dist(nowi,nowj)+1 )
          end do !iter
        end do
      end subroutine
      
      
      END PROGRAM