Skip to content

Instantly share code, notes, and snippets.

@aman-tiwari
Created November 17, 2017 07:16
Show Gist options
  • Save aman-tiwari/87c07a264f89820377ae8c0464dc1733 to your computer and use it in GitHub Desktop.
Save aman-tiwari/87c07a264f89820377ae8c0464dc1733 to your computer and use it in GitHub Desktop.
wfc with edge labels in clingo
#const n = 3.
% define?
cell(1..n, 1..n).
% kinds of edges
edge_kind(path).
edge_kind(empty).
% tiles, format:
% pdef((tile name, rotation in 90deg increments), bottom edge, right edge, top edge, left edge)
pdef((line_v, 0), path, empty, path, empty).
pdef((line_v, 1), empty, path, empty, path).
pdef((none, 0), empty, empty, empty, empty).
pdef((corner, 0), empty, empty, path, path).
pdef((corner, 1), path, empty, empty, path).
pdef((corner, 2), path, path, empty, empty).
pdef((corner, 3), empty, path, path, empty).
% edges that can connect to each other
connectable(path, path).
connectable(empty, empty).
connectable(E1, E2) :- edge_kind(E1), edge_kind(E2), connectable(E2, E1).
pattern(P) :- pdef(P, _, _, _, _).
dx(0, 1).
dx(1, 0).
dx(I, J) :- dx(-I, -J).
% any pattern can be placed on itself
legal(0, 0, P, P) :- pattern(P).
% P1 can be above P2 if P1's bottom edge and P2'
% top edge are connectable
legal(0, 1, P1, P2) :-
pdef(P1, E1, _, _, _),
pdef(P2, _, _, E2, _),
connectable(E1, E2).
% P1 can be left of P2 if P1's right edge and P2's
% left edge are connectable
legal(1, 0, P1, P2) :-
pdef(P1, _, E1, _, _),
pdef(P2, _, _, _, E2),
connectable(E1, E2).
% P1 can be below P2 if P1's top edge and P2's
% bottom edge are connectable
legal(0, -1, P1, P2) :-
pdef(P1, _, _, E1, _),
pdef(P2, E2, _, _, _),
connectable(E1, E2).
% P1 can be right of P2 if P1's left edge and P2's
% right edge are connectable
legal(-1, 0, P1, P2) :-
pdef(P1, _, _, _, E1),
pdef(P2, _, E2, _, _),
connectable(E1, E2).
% P1 can be left/below of P2 if P2 can be right/above P1
legal(DX, DY, P1, P2) :- legal(-DX, -DY, P2, P1).
% two positions are adjacent if they are within cells and the difference
% in x and y is equal to dx and dy
adj(X1, Y1, X2, Y2, DX, DY) :-
cell(X1, Y1), cell(X2, Y2),
dx(DX, DY), |X1 - X2|==DX, |Y1 - Y2|==DY.
% generate?
1 { assign(X,Y,P):pattern(P) } 1 :- cell(X,Y).
% fail if two cells are adjacent and one of them is assigned P1 at X1 Y1
% but no legal assignment for X2 Y2 exists
:- adj(X1,Y1,X2,Y2,DX,DY), assign(X1,Y1,P1),
not 1 { assign(X2,Y2,P2):legal(DX,DY,P1,P2) }.
% every pattern must be present at least 1 times
:- pattern(P), not 1 { assign(X,Y,P):cell(X,Y) }.
#show assign/3.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment