% Ce code est mis à la disposition des étudiants 
% qui peuvent l'utiliser et le compléter.

% HEXAPION

init([p(black,1,1), p(black,2,1), p(black,3,1),
      p(white,1,3), p(white,2,3), p(white,3,3)]).

hexa :- init(S), not(bad(S)), !,
        learn_maybe(S), play(white, S).

hexa :- nl, write('I cannot win.'), nl.

% Générer les coups

play(C, S) :- chessboard(S),
              ch_color(C, C1), win(C1, S),
              !, write('The winner is : '), write(C1), 
              nl, winner(C1), abort.

play(black, S) :- human(black, S, S_aft),
                  play(white, S_aft).

play(white, S) :- computer(white, S, S_aft),
                  play(black, S_aft).

% Prédicats auxiliaires

win(C, S) :- ch_color(C, C1), not(legal(C1,_,S)).
win(black, S) :- member(p(black,_,3), S).
win(white, S) :- member(p(white,_,1), S).

human(C,S1,S2) :- learn_maybe(S1), ask_human(C,M,S1),
                  move(M,S1,S2).

computer(C,S1,S2) :- possibility(C, S1, Ms), !,
                     choose_move(S1, Ms, M),
                     move(M, S1, S2).
computer(C,S1,_) :- learn(C, S1), end_msg, abort.

winner(black) :- !, maybe(S),
                 forget_maybe(S), learn_bad(S).
winner(white).

end_msg :- nl, write('I know that you are the winner').

% Coups possibles

choose_move(S, [M|Ms], M1) :-
        choose_win(S, [M|Ms], M1), !.
choose_move(_, [M|_], M).

choose_win(S,[M|_],M) :- move(M,S,S1),
                          win(white,S1), !.
choose_win(S,[_|Ms],M1) :- choose_win(S,Ms,M1).

possibility(C, S, [M1|M1s]) :-
        findall(M, legal(C, M, S), Ms),
        sub_bad(S, Ms, [M1|M1s]),
        maybe(S1), forget_maybe(S1).

legal(black, m(p(black,X,Y), p(black,X,Y1), forward), S)
   :- member(p(black,X,Y), S),
      incr(Y, Y1), free(X, Y1, S).

legal(white, m(p(white,X,Y), p(white,X,Y1), forward), S)
   :- member(p(white,X,Y), S),
      decr(Y, Y1), free(X, Y1, S).

legal(C, m(p(C,X,Y), p(C,X1,Y1), eat), S)
   :- member(p(C,X,Y), S), diag(C, X, Y, X1, Y1), 
      ch_color(C, C1), member(p(C1,X1,Y1), S).

move(m(P1, P2, forward), S_bef, S_aft)
   :- sub(P1, P2, S_bef, S), sort(S, S_aft).

move(m(P1, P2, eat), S_bef, S_aft)
   :- P2 = p(C2,X,Y), ch_color(C2, C),
      remove(p(C,X,Y), S_bef, S1),
      sub(P1, P2, S1, S), sort(S, S_aft).

% Manipulation de la configuration

is_range(X)  :- X>0, X=<3.     

incr(X, X1) :- X<3, X1 is X+1.
decr(X, X1) :- X>1, X1 is X-1.

diag(black, X, Y, X1, Y1) :- incr(Y, Y1), incr(X, X1).
diag(black, X, Y, X1, Y1) :- incr(Y, Y1), decr(X, X1).
diag(white, X, Y, X1, Y1) :- decr(Y, Y1), incr(X, X1).
diag(white, X, Y, X1, Y1) :- decr(Y, Y1), decr(X, X1).

ch_color(white, black).        

ch_color(black, white).

free(X, Y, S) :- not(member(p(_,X,Y),S)).

% Le dialogue avec l'adversaire

ask_human(C, m(P1,P2,Ty), S) :- can_move_it(C, P1, S),
                                where(m(P1,P2,Ty), S).

read_x(X) :- write('X: '), read(X), is_range(X), !.
read_x(X) :- read_x(X).

read_y(Y) :- write('Y: '), read(Y), is_range(Y), !.
read_y(Y) :- read_y(Y).

coord(X, Y) :- write('Enter the coordinate: '),
               nl, read_x(X), read_y(Y).

which_pawn(C, p(C,X,Y), S) :-
   nl, write('Which '), write(C),
   write(' pawn do you want to move ?'),
   nl, coord(X, Y), member(p(C,X,Y), S), !.

which_pawn(C, P, S) :- 
   write('There is not a '),
   write(C), write(' pawn there !'),
   nl, which_pawn(C, P, S).

can_move_it(C, P, S) :- 
   which_pawn(C, P, S), legal(C, m(P, _, _), S), !.

can_move_it(C, P, S) :-
   write('There is not a legal move for it!'),
   nl, can_move_it(C, P, S).


where(m(p(C,X1,Y1), p(C,X2,Y2), Type), S) :-
   nl, write('Where do you want to move it ?'),
   nl, coord(X2, Y2), 
   legal(C, m(p(C,X1,Y1), p(C,X2,Y2), Type), S), !.

where(M, S) :- write('This is not a legal move !'),
               nl, where(M, S).

% Gestion de l'apprentissage

show :- findall(S, bad(S), Ss), show_sit(Ss).

learn(C, S) :- findall(M, legal(C, M, S), Ms),
               forget(S, Ms), maybe(S1),
               forget_maybe(S1), learn_bad(S1).
     
forget(S, [M|Ms]) :- move(M, S, S1),
                     forget_bad(S1), forget(S, Ms).
forget(_, []).


sub_bad(S1, [M|M1s], M2s) :- move(M, S1, S2),
                             bad(S2), !,
                             sub_bad(S1, M1s, M2s).

sub_bad(S1, [M|M1s], [M|M2s]) :- sub_bad(S1, M1s, M2s).

sub_bad(_, [], []).

show_sit([[P|Ps]|Ss]) :- chessboard([P|Ps]),
                         show_sit(Ss).

show_sit([[]|Ss]) :- show_sit(Ss).

show_sit([]).
  

learn_bad([P|Ps]) :- asserta((bad([P|Ps]))).
learn_bad([]).

forget_bad([P|Ps]) :- retract((bad([P|Ps]))).
forget_bad([]).

learn_maybe([P|Ps]) :- asserta((maybe([P|Ps]))).
learn_maybe([]).

forget_maybe([P|Ps]) :- retract((maybe([P|Ps]))).
forget_maybe([]). 

bad([]).

maybe([]).

% Dessiner l'échiquier

chessboard(S) :- nl, nl, draw_coord_col, draw_border,
                 draw_board(1, S), draw_border, nl.

draw_board(Y,S) :- draw_line(Y,S), incr(Y,Y1), !,
                   draw_board(Y1,S).
draw_board(_,_).

draw_line(Y,S) :- write(' '),write(Y),write(' |'),
                  draw_line(1,Y,S),write('|'),nl.
draw_line(X,Y,S) :- draw_cell(X,Y,S),incr(X,X1),!,
                    draw_line(X1,Y,S).
draw_line(_,_,_).

draw_cell(X, Y, S) :- member(p(C,X,Y), S), !, draw_pawn(C).
draw_cell(_, _, _) :- write(' ').

draw_pawn(white) :- write('W').
draw_pawn(black) :- write('B').

draw_coord_col :- Xd is 3//10, write('    '),
                  draw_ten(1, Xd), nl,
                  write('    '), draw_num(3), nl.

draw_ten(N,M) :- N=<M, !, write('         '), write(N),
                 N1 is N+1, draw_ten(N1,M).
draw_ten(_,_).

draw_num(N) :- N>9, number(9,Xs), draw(Xs),
               write('0'), N1 is N-10, draw_num(N1).

draw_num(N) :- N=<9, N>0, number(N, Xs), draw(Xs).

draw_num(0).

draw_border :- make_list(3,'-',Bord), write('   +'),
               draw(Bord), write('+'), nl.

remove(X, [X|Xs], Xs).

remove(X, [Y|Ys], [Y|Zs]) :-
     X\==Y, remove(X, Ys, Zs).

sub(X, Y, [X|Xs], [Y|Xs]).

sub(X, Y, [Z|Xs], [Z|Ys]) :- sub(X, Y, Xs, Ys).

make_list(N, X, [X|Xs]) :-
     N>0, N1 is N-1, make_list(N1, X, Xs).

make_list(0, _, []).  

draw([X|Xs]) :- write(X), draw(Xs).
draw([]).

number(N, Xs) :- number(1, N, Xs).
number(N, N, [N]).
number(S, N, [S|Xs]) :- S<N, S1 is S+1, number(S1, N, Xs).

before(p(black,_,_), p(white,_,_)) :- !.
before(p(C,X1,_), p(C,X2,_)) :- X1 < X2, !.
before(p(C,_,Y1), p(C,_,Y2)) :- Y1 < Y2.

/* EXEMPLE DE PARTIE

?- hexa.
    
    123     123
   +---+   +---+
 1 |BBB| 1 |BBB|
 2 |   | 2 |W  |
 3 |WWW| 3 | WW|
   +---+   +---+

Which black pawn do you want to move ?
Enter the coordinate: 
X: 2.
Y: 1.

Where do you want to move it ?
Enter the coordinate: 
X: 1.
Y: 2.

    123     123
   +---+   +---+
 1 |B B| 1 |B B|
 2 |B  | 2 |BW |
 3 | WW| 3 |  W|
   +---+   +---+
\end{verbatim}

\newpage\rm

{\LARGE\bf Apprentissage en Prolog XX}

\bg\bg

PREMIERE PARTIE (bis)

\bg\sf

\begin{verbatim}
    123     123
   +---+   +---+
 1 |B B| 1 |B B|
 2 |BW | 2 | W |
 3 |  W| 3 |B W|
   +---+   +---+

The winner is : black
Execution Aborted






?- show.

    123
   +---+
 1 |B B|
 2 |BW |
 3 |  W|
   +---+


% DEUXIEME PARTIE

    123     123     123     123     123 
   +---+   +---+   +---+   +---+   +---+
 1 |BBB| 1 |BBB| 1 |B B| 1 |B B| 1 |B B|
 2 |   | 2 |W  | 2 |B  | 2 |B W| 2 |  W|
 3 |WWW| 3 | WW| 3 | WW| 3 | W | 3 |BW |
   +---+   +---+   +---+   +---+   +---+

The winner is : black
Execution Aborted

    123    123
   +---+   +---+
 1 |B B| 1 |B B|
 2 |B W| 2 |BW |
 3 | W | 3 |  W|
   +---+   +---+
% PROGRESSION DE L'APPRENTISSAGE


\begin{verbatim}
    123     123     123 
   +---+   +---+   +---+
 1 |B B| 1 |B B| 1 |B B|
 2 |W  | 2 |B W| 2 |BW |
 3 |  W| 3 | W | 3 |  W|
   +---+   +---+   +---+

    123     123     123 
   +---+   +---+   +---+
 1 |BBB| 1 |BBB| 1 |B B|
 2 |   | 2 |W  | 2 |B  |
 3 |WWW| 3 | WW| 3 | WW|
   +---+   +---+   +---+

I know that you are the winner

?- show.
    
    123
   +---+
 1 |BBB|
 2 |W  |
 3 | WW|
   +---+

% Entame centrale

?- hexa.
    
    123     123     123     123     123
   +---+   +---+   +---+   +---+   +---+
 1 |BBB| 1 |BBB| 1 | BB| 1 | BB| 1 | BB|
 2 |   | 2 | W | 2 | B | 2 |WB | 2 |W  |
 3 |WWW| 3 |W W| 3 |W W| 3 |  W| 3 | BW|
   +---+   +---+   +---+   +---+   +---+
    
The winner is : black
Execution Aborted

% FIN DE L'APPRENTISSAGE, SITUATIONS PERDANTES


    123     123     123    
   +---+   +---+   +---+
 1 |BBB| 1 |BBB| 1 |BBB|
 2 |W  | 2 | W | 2 |  W|
 3 | WW| 3 |W W| 3 |WW |
   +---+   +---+   +---+

    123
   +---+
 1 |BBB|
 2 |   |
 3 |WWW|
   +---+

I know that you are the winner
Execution Aborted

*/
