Chessboard maze

VBA 668 666 633 622 548 510 489 435 331 322 319 315 bytes

Function Z(F):Dim X(7,7):While Q<64:R=R+1:V=Asc(Mid(F,R))-48:If V>9 Then X(Q\8,Q Mod 8)=(3+(V\8=V/8))*Sgn(48-V):V=1
Q=Q-V*(V>0):Wend:X(7,0)=1:For W=0 To 2E3:Q=W Mod 8:P=W\8 Mod 8:For T=Q+(Q>0) To Q-(Q<7):For S=P+(P>0) To P-(P<7):If X(S,T)=0 Then X(S,T)=(1=X(P,Q))*(6>X(P,T)*X(S,Q))
Next S,T,W:Z=X(0,7):End Function

Reading the input string occupies up to 'Wend'. Nice side effect - this abandons the input string once the board [X] is fully coded, so you can leave a description on the end.

In the board coding, pawns are 2, other pieces are 3, black is negative. Pawns are recognized by 'P' & 'p' having character codes divisible by 8.

'X(7,0)=1', setting a1 accessible, is where the path checks start. This repeatedly scans the board trying to add accessible squares from squares marked as accessible (1) so far. Diagonal access and occupancy are checked in a IF + logic-calc which once lived in a function but now sits in nested neighbour loops. The diagonal access check relies on the product of the two kitty-corner squares, which is only at 6 or more if pieces there are the same colour and at least one is a piece not a pawn.

Call in spreadsheet; returns the value in X(0,7) - 1 if h8 accessible and 0 if not - which Excel recognizes as truthy / falsy. =IF(Z(C2), "yes","no")

enter image description here

I maybe got carried away with scrunching the code down, above, so here is a semi-ungolfed commented version:

Function MazeAssess(F)  'input string F (FEN)
Dim X(7, 7)             'size/clear the board; also, implicitly, Q = 0: R = 0
'Interpret string for 8 rows of chessboard
While Q < 64
    R = R + 1           ' next char
    V = Asc(Mid(F, R)) - 48  ' adjust so numerals are correct
    If V > 9 Then X(Q \ 8, Q Mod 8) = (3 + (V \ 8 = V / 8)) * Sgn(48 - V): V = 1 ' get piece type (2/3) and colour (+/-); set for single column step
    Q = Q - V * (V > 0) ' increment column (unless slash)
Wend
'Evaluate maze
X(7, 0) = 1             ' a1 is accessible
For W = 0 To 2000       ' 1920 = 30 passes x 8 rows x 8 columns, golfed to 2E3
    Q = W Mod 8         ' extracting column
    P = W \ 8 Mod 8     ' extracting row
    For T = Q + (Q > 0) To Q - (Q < 7)     ' loop on nearby columns Q-1 to Q+1 with edge awareness
        For S = P + (P > 0) To P - (P < 7) ' loop on nearby rows (as above)
            If X(S, T) = 0 Then X(S, T) = (1 = X(P, Q)) * (6 > X(P, T) * X(S, Q)) ' approve nearby empty squares if current square approved and access is possible
        Next 'S
    Next 'T
Next 'W
MazeAssess = X(0, 7)    ' report result for h8
End Function

Progress notes

Edit1: The code is now not as 666-devilish :-D and has lost its functions; I found a short-enough way to write them to avoid the overhead.

Edit2: Another biggish leap forward, effectively finishing the work of removing the inc/dec functions, sigh, and using a couple of globals. I might finally be getting the hang of this....

The coding of pieces & squares changed. No effect on code length.

Edit3: Return of (fake) functions, removing all those annoying Call bytes, and some other tweaks.

Edit4: Breaking through the big 500, woohoo - smooshed the 3 For loops into 1.

Edit5: Jiminy Cricket, another big drop when I smooshed the two functions together - my diagonal access check always passes for adjacent squares, so...

Edit6: Holy niblicks, another massive drop. Buh-bye to external functions and thus globals... I have gone to under half the original posted length....

Edit7: Add ungolfed version

Edit8: Revised the read process for a few dollars more

Edit9: Squeezed a couple of expressions for the last few drops of blood

Edit10: Compund Next statement sheds a few bytes


For interest, graphics of the boards after accessibility analysis (the code numbers are out of date but...) accessible squares are green, inaccessible squares white and other colours are pieces or pawns.

3 successful boards 3 blocked boards

A couple of challenge boards: h8 is accessible in both:

  • P1Pq2p1/1P1R1R1p/1K2R1R1/1p1p1p2/p1b1b1np/1B1B1N1k/Q1P1P1N1/1r1r1n2 - 10 passes to solve
  • P1P3r1/1P1R2r1/1N1R1N2/1P1P1P2/1n1p1ppp/1B1B4/1b1pppp1/1P6 - a winding path

Matlab, 636 887 bytes as saved (including indentation)

This solution is not very golfed, but I wanted to go ahead and put it up.

function[n] = h(x)
o=[];
for i=x
 b={blanks(str2num(i)),'K','k',i};o=[o b{~cellfun(@isempty,regexp(i,{'\d','[NBRQK]','[nbrqk]','p|P'}))}];
end
o=fliplr(reshape(o,8,8))
for i=1:64
 b=i-[-8,8,7,-1,-9,1,9,-7];
 if mod(i,8)==1
  b=b(1:5);
 elseif mod(i,8)==0
  b=b([1,2,6:8]);
 end
 b=b(b<65&b>0);c=o(b);dn=b(isspace(c)&ismember(b,i-[9,7,-9,-7]));
 for j=dn
  g=o(b(ismember(b,j-[-8,8,7,-1,-9,1,9,-7])));
  if ~isempty(regexp(g,'pk|kp|PK|KP|kk|KK'));c(b==j)='X';end;
 end
 Bc{i}=b(c==32);
end
n=Bc{1};
on=[];
while length(n)>length(on)
 on=n;
 for i=1:length(n)
  n=unique([n Bc{n(i)}]);
 end
end
any(n==64)
end

Reads a board string x as specified above and turns it into the more completely represented o, then finds all the moves (graph edges) between spaces, then figures out which moves are possible (not into filled spaces), then figures out which possible moves have "gates" of two pieces to pass between, then figures out if the gate is open (pawns, opposite colors) or closed (same color and including a non-pawn). Then, it walks through to find locations reachable by paths from the lower left square and if a path can reach space 64, it's a Yes board.