/* Tic tac toe from PLP 11.3*/

:- dynamic o/1.
:- dynamic x/1.

ordered_line(1,2,3).  ordered_line(4,5,6).  ordered_line(7,8,9).
ordered_line(1,4,7).  ordered_line(2,5,8).  ordered_line(3,6,9).
ordered_line(1,5,9).  ordered_line(3,5,7).
line(A, B, C) :- ordered_line(A, B, C).  line(A, B, C) :- ordered_line(A, C, B). 
line(A, B, C) :- ordered_line(B, A, C).  line(A, B, C) :- ordered_line(B, C, A). 
line(A, B, C) :- ordered_line(C, A, B).  line(A, B, C) :- ordered_line(C, B, A). 

full(A) :- x(A).  full(A) :- o(A).  empty(A) :- not(full(A)).

same(A, A).  different(A, B) :- not(same(A, B)).

move(A) :- good(A), empty(A), !.

/* Strategy */
good(A) :- win(A).
good(A) :- block_win(A).
good(A) :- split(A).
good(A) :- block_split(A).
good(A) :- build(A).

good(5).  good(1).  good(3).  good(7).  good(9).  
good(2).  good(4).  good(6).  good(8).

win(A) :- x(B), x(C), line(A,B,C).
block_win(A) :- o(B), o(C), line(A,B,C).
split(A) :- x(B), x(C), different(B,C), line(A,B,D), line(A,C,E), empty(D), empty(E).
block_split(A) :- o(B), o(C), different(B,C), line(A,B,D), line(A,C,E), empty(D), empty(E).
build(A) :- x(B), line(A,B,C), empty(C).

all_full :- full(1), full(2), full(3), full(4), full(5), full(6), full(7), full(8), full(9).

done :- ordered_line(A,B,C), x(A), x(B), x(C), write('I won.'), nl.
done :- ordered_line(A,B,C), o(A), o(B), o(C), write('You won.'), nl.  % should NOT happen
done :- all_full, write('Draw.'), nl.

getmove :- repeat, write('Please enter a move: '), read(X), empty(X), assert(o(X)).
makemove :- move(X), !, assert(x(X)).
makemove :- all_full.

printsquare(N) :- o(N), write(' o ').
printsquare(N) :- x(N), write(' x ').
printsquare(N) :- empty(N), write('   ').
printboard :-
	printsquare(1), printsquare(2), printsquare(3), nl,
	printsquare(4), printsquare(5), printsquare(6), nl,
	printsquare(7), printsquare(8), printsquare(9), nl.
clear :- x(A), retract(x(A)), fail.
clear :- o(A), retract(o(A)), fail.

% main goal:
play :- not(clear), repeat, getmove, makemove, printboard, done.

