Acciones

Heyawake

De Lógica computacional y teoría de modelos (2019-20)

%% Heyawake

%% Es un juego que consiste en, teniendo una cuadricula con unos ciertos números y habitaciones, pintar ciertas celdas de negro según las reglas siguientes:

%% R1: Cualquiera dos celdas negras no pueden ser horizontalmente o verticalmente adyacentes la una con la otra.
%% R2: Todas las celdas blancas tienen que estar conectadas.
%% R3: Un número en una habitación indica el número de celdas negras que hay en esta.
%% R4: Si una habitación no contiene ningún número, entonces puede contener cualquier número de celdas negras.
%% R5: Ningún camino recto que conecte dos celdas blancas pasa por más de dos habitaciones.

%% Estaticos.

col(1..c). fila(1..f). num(0..r-1). segmento(h;v).

%% Primero antes de entrar en las restricciones y generación de la solución definamos algnos conceptos
%% auxiliares.

%Posición.

pos(X,Y) :- fila(X), col(Y).

% Adyacencia.

adj(X,Y,U,V) :- |X-U| + |Y-V| == 1,
                col(Y), col(V), fila(X), fila(U).

% Blanco. Aquellas celdas que al generar no sean negras, serán blancas.

blanco(X,Y) :- not negro(X,Y), fila(X), col(Y).

% Conexión de dos celdas blancas.

conectado(X,Y,U,V) :- adj(X,Y,U,V), blanco(X,Y), blanco(U,V).
conectado(X,Y,U,V) :- conectado(X,Y,W,Z), adj(W,Z,U,V), blanco(U,V).

% La celda (X,Y) está en la habitación A.

en_habi(X,Y,A) :- habi(A,F,C,F1,C1), X<=F1, F<=X, Y<=C1, C<=Y,
                  fila(X), col(Y).

% Número de habitaciones por el que pasa un camino recto entre celdas blanca.

camino(S,X,Y,X,Y,1) :- blanco(X,Y), segmento(S).

camino(v,X,Y,Z,Y,N) :- camino(v,X+1,Y,Z,Y,N), blanco(X,Y), en_habi(X,Y,A), en_habi(X+1,Y,A).
camino(v,X,Y,Z,Y,N+1) :- camino(v,X+1,Y,Z,Y,N), blanco(X,Y), en_habi(X,Y,A), en_habi(X+1,Y,B),
                         A!=B, X<Z.

camino(h,X,Y,X,Z,N) :- camino(h,X,Y+1,X,Z,N), blanco(X,Y), en_habi(X,Y,A), en_habi(X,Y+1,A).
camino(h,X,Y,X,Z,N+1) :- camino(h,X,Y+1,X,Z,N), blanco(X,Y), en_habi(X,Y,A), en_habi(X,Y+1,B),
                         A!=B, Y<Z.


%% Generación. Para generar cuadrículas usaremos también R3 y R4.
%% R3: Un número en una habitación indica el número de celdas negras que hay en ésta.

N{negro(X,Y) : X1<=X, X<=X2, Y1<=Y, Y<=Y2, pos(X,Y)}N :- habi(A,X1,Y1,X2,Y2), tiene(A,N), N!=-1.

%% R4: Si una habitación no contiene ningún número, entonces puede contener cualquier número de celdas negras.

{negro(X,Y) : X1<=X, X<=X2, Y1<=Y, Y<=Y2, pos(X,Y)} :- habi(A,X1,Y1,X2,Y2), tiene(A,-1).

%% R1: Cualquiera dos celdas negras no pueden ser horizontalmente o verticalmente adyacentes la una con la otra.

:- adj(X,Y,Z,Y), negro(X,Y), negro(Z,Y), X!=Z.
:- adj(X,Y,X,Z), negro(X,Y), negro(X,Z), Y!=Z.

%% R2: Todas las celdas blancas tienen que estar conectadas.

:- not conectado(X,Y,U,V), blanco(X,Y), blanco(U,V), (X,Y)!=(U,V).

%% R5: Ningún camino recto que conecte dos celdas blancas pasa por más de dos habitaciones.

:- camino(S,X,Y,U,V,3), blanco(X,Y), blanco(U,V).

%% Presentación.

#show negro/2.