% Auteur:
% Date: 08/12/2010

dame_imprenable(Taille) :- setof(X, dame(Taille, X), R), print_tout_damiers(R).

% Check si dans une liste, pas plus de un 1
ligne_check([0]).
ligne_check([1|T]) :- maplist(=(0), T).
ligne_check([0|T]) :- ligne_check(T).

% Idem pour une liste de liste
lignes_check(Damiers) :- maplist(ligne_check, Damiers).

% Permet de simuler une matrice à partir d'une liste de liste
nth_matrice(Damiers, I, J, E) :- nth1(J, Damiers, E1), nth1(I, E1, E).

% Récupère les diagonales sous formes de liste de liste
diag1(Damiers, Taille, J, [E], Taille) :- nth_matrice(Damiers, Taille, J, E).
diag1(Damiers, I, Taille, [E], Taille) :- nth_matrice(Damiers, I, Taille, E).
diag1(Damiers, I, J, [E|E1], Taille) :-
between(1, Taille, I), between(1, Taille, J),
I1 is I+1, J1 is J+1,
nth_matrice(Damiers, I, J, E),
diag1(Damiers, I1, J1, E1, Taille).
diag_a(Damiers, Taille, Taille, [L]) :- diag1(Damiers, Taille, 1, L, Taille).
diag_a(Damiers, I, Taille, [T|Q]) :-
between(1, Taille, I),
I1 is I+1,
diag1(Damiers, I, 1, T, Taille),
diag_a(Damiers, I1, Taille, Q).
diag_b(Damiers, Taille, Taille, [L]) :- diag1(Damiers, 1, Taille, L, Taille).
diag_b(Damiers, I, Taille, [T|Q]) :-
between(1, Taille, I),
I1 is I+1,
diag1(Damiers, 1, I, T, Taille),
diag_b(Damiers, I1, Taille, Q).
diag(Damiers, Taille, Lst) :-
diag_a(Damiers, 1, Taille, L1),
diag_b(Damiers, 2, Taille, L2),
append(L1, L2, Lst).

% Appelles les différentes contraintes du jeu
dame(Taille, Damiers) :-
length(Damiers, Taille), maplist(length_(Taille), Damiers),
lignes_check(Damiers),
tps(Damiers, Ts, Taille), lignes_check(Ts),
diag(Damiers, Taille, Diags), lignes_check(Diags).

% Pour maplist la taille des colonnes
length_(L, Ls) :- length(Ls, L).

% Inverse une matrice : pour pouvoir check les colonnes
tps(D, T, Taille) :- liste_colonnes(D, 1, Taille, T).
colonne(D, N, Taille, Taille, [T]) :- nth_matrice(D, N, Taille, T).
colonne(D, N, I, Taille, [T|Q]) :-
nth_matrice(D, N, I, T),
I1 is I + 1,
colonne(D, N, I1, Taille, Q).
liste_colonnes(D, Taille, Taille, [T]) :- colonne(D, Taille, 1, Taille, T).
liste_colonnes(D, I, Taille, [T|Q]) :-
colonne(D, I, 1, Taille, T),
I1 is I + 1,
liste_colonnes(D, I1, Taille, Q).

% Fonction d'affichage
print_tout_damiers(Ld) :- maplist(print_damiers, Ld).
print_damiers(D) :-  maplist(print_ligne, D), nl.
print_ligne(L) :-  maplist(write, L), nl.
