%% Nurikabe.
%% Es un juego que consiste en, dado una cuadrícula en blanco con unos ciertos números,
%% pintar algunas de las celdas de negro en base a unas reglas de forma que las
%% celdas de negro son agua y las celdas blancas formas islas. Las reglas que se
%% tienen que cumplir son las siguientes:
%% R1: Las celdas enumeradas son blancas.
%% R2: Toda celda blanca pertenece a una isla.
%% R3: Cada isla contiene exactamente una celda enumerada.
%% R4: Cada isla tiene que contener el mismo número de celdas blancas que el número que contiene.
%% R5: Las celdas blancas tienen que estar conectadas ortogonalmente.
%% R6: Dos islas no pueden estar conectadas.
%% R7: Todas las celdas negras tienen que estar conectadas ortogonalmente.
%% R8: Ningún conjunto de celdas negras forma un cuadrado 2 x 2.
%% Estaticos.
col(1..c).
fila(1..r).
color(blanco;negro).
%% Generación. Para generar las soluciones, en cada posición elegimos si la celda es blanca o no.
pos(X,Y) :- fila(X), col(Y).
{cel(X,Y,blanco)}1 :- pos(X,Y).
%% Cada celda que no haya elegido para ser blanca será negra.
cel(X,Y,negro) :- not cel(X,Y,blanco), pos(X,Y).
%% Una vez generado los tableros, pasamos a escribir las restricciones.
%% Primero describiremos las conexiones que tiene que haber entre celdas.
% Celdas que están conectadas ortogonalmente.
ortogonal(F,C,F1,C1) :- pos(F,C), pos(F1,C1), |F-F1|+|C-C1|== 1.
% Celdas que están color-conectadas por un camino ortogonal.
conectado(C,X,Y,X,Y) :- cel(X,Y,C).
conectado(C,X,Y,U,V) :- conectado(C,X,Y,W,Z), ortogonal(W,Z,U,V), cel(U,V,C).
% Celdas blancas que estan conectadas a una celda enumerada.
b_conectado(X,Y) :- conectado(blanco,X,Y,U,V), cel(X,Y,blanco), numero(U,V,N).
%% R1: Las celdas enumeradas son blancas.
cel(X,Y,blanco) :- numero(X,Y,N).
%% R2: Toda celda blanca pertenece a una isla.
%% R5: Las celdas blancas tienen que estar conectadas ortogonalmente.
:- cel(X,Y,blanco), not b_conectado(X,Y).
%% R3: Cada isla contiene exactamente una celda enumerada.
%% R6: Dos islas no pueden estar conectadas.
%% Estas dos reglas se pueden ver como que dos celdas enumeradas no pueden estar conectadas.
:- conectado(blanco,X,Y,U,V), numero(X,Y,N), numero(U,V,N1), (X,Y) != (U,V).
%% R4: Cada isla tiene que contener el mismo número de celdas blancas que el número que contiene.
isla(X,Y) :- N{conectado(blanco,X,Y,U,V): pos(U,V)}N, numero(X,Y,N).
:- not isla(X,Y), numero(X,Y,N).
%% R7: Todas las celdas negras tienen que estar conectadas ortogonalmente.
:- cel(X,Y,negro), cel(U,V,negro), not conectado(negro,X,Y,U,V).
%% R8: Ningún conjunto de celdas negras forma un cuadrado 2 x 2.
:- cel(X,Y,negro), cel(X+1,Y,negro), cel(X,Y+1,negro), cel(X+1,Y+1,negro).
%% Presentación.
negro(X,Y) :- cel(X,Y,negro).
#show negro/2.