Infinite Labyrinths
C# - 423 375 bytes
Complete C# program, accepts input via STDIN, outputs "True" or "False" to STDOUT as appropriate.
I could not bare to leave that Linq in there... thankfully its removal paid off! It now keeps track of seen and visited cells in an array (given it only ever looks at a finite number of them anyway). I also re-wrote the directional code, removing the need for a Lambda, and generally making the code more impossible to understand (but with substantial byte savings).
using C=System.Console;struct P{int x,y;static void Main(){int w=0,W,k=0,o,i,j;P t;string D="",L;for(;(L=C.ReadLine())!=null;D+=L)w=L.Length;for(i=W=D.Length;i-->0&k<W;){k=1;P[]F=new P[W];for(F[j=0].x=i%w+W*W,F[0].y=i/w+W*W;D[i]>35&j<k;)for(t=F[j++],o=1;o<5&k<W;t.y+=(o++&2)-1){t.x+=o&2;if(D[--t.x%w+t.y%(W/w)*w]>35&System.Array.IndexOf(F,t)<0)F[k++]=t;}}C.WriteLine(k>=W);}}
It is a breadth-first (not that this matters) search which just carries on until it either gets stuck in a finite cavern, or it decides the cavern is big enough that it must be infinitely large (when it has as many cells as the original rectangle, this means there must be a path from one cell to itself somewhere else, which we can continue to follow forever).
Untrimmed code:
using C=System.Console;
struct P
{
int x,y;
static void Main()
{
int w=0, // w is the width
W, // W is the length of the whole thing
k=0, // k is visited count
o, // o is offset, or something (gives -1,0 0,-1 +1,0 0,+1 t offset pattern)
i, // i is the start cell we are checking currently
j; // j is the F index of the cell we are looking at
P t; // t is the cell at offset from the cell we are looking at
string D="", // D is the map
L;
for(;(L=C.ReadLine())!=null; // read a line, while we can
D+=L) // add the line to the map
w=L.Length; // record the width
for(i=W=D.Length;i-->0&k<W;) // for each cell
{
k=1;
P[]F=new P[W]; // F is the list of visited cells,
for(F[j=0].x=i%w+W*W,F[0].y=i/w+W*W; // there are reasons (broken modulo)
D[i]>35&j<k;) // for each cell we've visited, until we've run out
for(t=F[j++], // get the current cell
o=1; // o is just a counter which we use to kick t about
o<5& // 4 counts
k<W; // make sure we havn't filled F
t.y+=(o++&2)-1) // kick and nudge y, inc o
{
t.x+=o&2; // kick x
if(D[--t.x%w+t.y%(W/w)*w]>35 // nudge x, it's a dot
&System.Array.IndexOf(F,t)<0) // and we've not seen it before
F[k++]=t; // then add it
}
}
C.WriteLine(k>=W); // result is whether we visited lots of cells
}
}
Python 2 - 258 210 244 bytes
Recursively check paths, if stack overflow return 1 (truthy) else return None (falsey).
import sys
def k(s):
a=len(s);m=[[c=='.'for c in b]*999for b in s.split('\n')]*999;sys.setrecursionlimit(a)
for x in range(a*a):
try:p(m,x/a,x%a)
except:return 1
def p(m,x,y):
if m[x][y]:m[x][y]=0;map(p,[m]*4,[x,x,x+1,x-1],[y+1,y-1,y,y])
Python 2 - 297 286 275 bytes
Picks an arbitrary "open" cell to begin a flood fill from. Labyrinth is infinite if during the fill we re-visit a cell we've already visited, but it has a different coordinate to the previous visit. If the flood fill fills the entire region without finding such a cell, try a different region. If such a region can't be found, the labyrinth is finite.
Takes file to process on command line, returns exit code 1
for infinite, and 0
for finite.
Returns correct results for all test cases.
import sys
e=enumerate
C=dict([((i,j),1)for i,l in e(open(sys.argv[1]))for j,k in e(l)if'.'==k])
while C:
d={}
def f(r,c):
n=(r%(i+1),c%j)
if n in d:return(r,c)!=d[n]
if C.pop(n,0):d[n]=(r,c);return any(map(f,[r-1,r,r+1,r],[c,c+1,c,c-1]))
if f(*C.keys()[0]):exit(1)