Acciones

Nurikabe

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

%% 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.