module mod_queue
  implicit none

  type t_node
    private
    integer :: item
    type(t_node), pointer :: prev => null()
    type(t_node), pointer :: next => null()
  end type t_node

  type t_queue
    private
    integer :: num = 0
    type(t_node), pointer :: head => null()
    type(t_node), pointer :: tail => null()
  contains
    procedure :: enqueue => enqueue
    procedure :: dequeue => dequeue
    procedure :: peek => peek
    procedure :: clear => clear
    procedure :: size => size_of
  end type t_queue

contains


  function new_node(item) result(node)
    integer, intent(in) :: item
    type(t_node), pointer :: node

    allocate(node)
    node%item = item
  end

  subroutine enqueue(this,item)
    class(t_queue), intent(inout) :: this
    integer, intent(in) :: item
    type(t_node), pointer :: node

    node => new_node(item)
    if (associated(this%head)) then
      node%prev => this%tail
      this%tail%next => node
    else
      this%head => node
    end if
    this%tail => node
    this%num = this%num+1
  end

  function dequeue(this) result(item)
    class(t_queue), intent(inout) :: this
    integer :: item
    type(t_node), pointer :: node

    item = this%head%item
    node => this%head%next
    deallocate(this%head)
    this%head => node
    if (associated(node)) then
      node%prev => null()
    else
      this%tail => null()
    end if
    this%num = this%num-1
  end

  function peek(this) result(item)
    class(t_queue), intent(in) :: this
    integer :: item

    item = this%head%item
  end

  subroutine clear(this)
    class(t_queue), intent(inout) :: this
    type(t_node), pointer :: node, next

    if (.not.associated(this%head)) return
    node => this%head
    do while (associated(node%next))
      next => node%next
      deallocate(node)
      node => next
    end do
    this%head => null()
    this%tail => null()
    this%num = 0
  end

  integer function size_of(this)
    class(t_queue), intent(in) :: this

    size_of = this%num
  end

end module mod_queue

module maze
integer,allocatable,dimension(:,:)::mazemap
integer::dirx(4)=[1,0,-1,0]
integer::diry(4)=[0,1,0,-1]

integer ans

contains

subroutine getmap(mazemap,R,C)
  integer,allocatable,dimension(:,:)::mazemap
  integer R,C
  character(1000) linereader
  allocate(mazemap(0:R+1,0:C+1))
  mazemap=0
  do i=1,R
    read*,linereader
    do j=1,C
      if(linereader(j:j)==".")mazemap(i,j)=-1
    end do
  end do
end subroutine
end module maze
use mod_queue
use maze
integer H,W
type(t_queue) :: pq(2)
read*,H,W
call getmap(mazemap,H,W)
do i=1,H
  do j=1,W
    if(mazemap(i,j)==0)then
      do k=1,4
        if(mazemap(i+dirx(k),j+diry(k) )==-1)then
          mazemap(i+dirx(k),j+diry(k) )=1
          call enqueue(pq(1),i+dirx(k))
          call enqueue(pq(2),j+diry(k))
        endif
      end do
    endif
  end do
end do

ans=0
do while(size_of(pq(1))/=0)
  itemsize=size_of(pq(1))
  do ii=1,itemsize
    i=dequeue(pq(1))
    j=dequeue(pq(2))
    do k=1,4
      if(mazemap(i+dirx(k),j+diry(k) )==-1)then
        mazemap(i+dirx(k),j+diry(k) )=mazemap(i,j)+1
        ans=max(ans,mazemap(i,j)+1)
        call enqueue(pq(1),i+dirx(k))
        call enqueue(pq(2),j+diry(k))
      endif
    end do
  end do
end do

print"(I0)",ans

end