% This buffer is for notes you don't want to save.
% If you want to create a file, visit that file with C-x C-f,
% then enter the text in that file's own buffer.

:- dynamic caminho/1,last_action/1.

bloco(a).
bloco(b).
bloco(c).
bloco(d).
bloco(e).
bloco(f).


meta([livre(a),sobre(a,c),sobre(c,b),sobre(b,d),sobre_a_mesa(d),braco_vazio]).
atual([livre(d),sobre(b,a),sobre(c,b),sobre(d,c),sobre_a_mesa(a),braco_vazio]).

%meta([livre(a),sobre(a,b),sobre_a_mesa(b),braco_vazio]).
%atual([livre(b),sobre(b,a),sobre_a_mesa(a),braco_vazio]).

caminho([]).
last_action([]).

inicia :-
	abolish(caminho/1), 
	assert(caminho([])),
	abolish(last_action/1), 
	assert(last_action([])),
	atual(Atual),
	meta(Meta),
	meios_fins(Atual,Meta).

diferenca(_,[],[]).
diferenca(E,[X|Y],[X|Z]) :-
	\+ member(X, E),
	diferenca(E,Y,Z),!.
diferenca(E,[_|Y],Z) :-
	diferenca(E,Y,Z).

meios_fins(Atual,Meta) :-
	diferenca(Atual,Meta,D),
	D == [].

meios_fins(Atual,Meta) :-
	diferenca(Atual,Meta,Diferenca),
%	member(X,Diferenca),
	reduz_diferencas(Diferenca,Atual,Meta).

%reduz_diferenca(D,A,_,A) :-
%	member(D,A).
reduz_diferenca(X,Atual,Meta,S) :-
	seleciona_operador(X,Atual,Meta,S).

reduz_diferencas(X,Atual,Meta) :-
	seleciona_operador1(X,Atual,Meta).

adiciona_caminho(X) :-
	caminho(Y),
	append([X],Y,W),
	retractall(caminho(_)),
	assert(caminho(W)).
nao_visitado(X) :-
	caminho(C),
%	\+member(X,C),
	\+percorrido(X,C),
	adiciona_caminho(X).

percorrido([Op,E],[[Op,Y]|_]) :-
	diferenca(E,Y,W),
	diferenca(Y,E,W1),
	W == W1,
	W == [],!.
percorrido(X,[_|Y]) :-
	percorrido(X,Y).

seleciona_operador(Diferenca,Atual,Meta,S) :-
	operador(O,_,_,_,_),
	faca(O,Atual,S,P),
	member(Diferenca,S),
	write([O,Diferenca,Atual]),nl,
	meios_fins(Atual,P,_),
	meios_fins(S,Meta,_).
%	append(Primeira_Parte,Ultima_Parte,Resultado).

seleciona_operador1(Diferenca,Atual,Meta) :-
	Diferenca \= [],
	operador(O,_,_,_,_),
	faca(O,Atual,S,P),
	nao_visitado([O,S]),
	diferenca(S,Diferenca,L),length(L,X),length(Diferenca,Y), X =< Y,
	\+ go_back_action([O,S]),
	insert_last_action([O,Atual]),
	write([O,S]),nl,
	meios_fins(Atual,P),
	meios_fins(S,Meta).
%	append(Primeira_Parte,Ultima_Parte,Resultado).

go_back_action([_,P]) :-
	last_action([_,P1]),
%	faca(A,P,E1,_),
	diferenca(P,P1,W),
	diferenca(P1,P,W1),
	W == [],W == W1.

insert_last_action(X):-
	retractall(last_action(_)),
	assert(last_action(X)).

% nome, variaveis, precondicoes, remove, add
operador(desempilhar, 
	 [sobre(X,Y),livre(X), braco_vazio], %livre(X)
	 [sobre(X,Y),braco_vazio],
	 [segurando(X),livre(Y)],(X\=Y)).  %Y X

operador(empilhar,
	 [livre(Y),segurando(X)],
	 [livre(Y),segurando(X)],
	 [braco_vazio,sobre(X,Y)],(X\=Y)).

operador(pegar,
	 [livre(X),sobre_a_mesa(X),braco_vazio],
	 [sobre_a_mesa(X),braco_vazio],
	 [segurando(X)],true).

operador(largar,
	 [segurando(X)],
	 [segurando(X)],
	 [sobre_a_mesa(X),braco_vazio],true).

/*
operador(largar_sobre,
	 [segurando(X),livre(Y)],
	 [segurando(X),livre(Y)],
	 [sobre(X,Y),livre(X),braco_vazio],true).
*/

faca(Op, Atual, S,Pre) :-
	operador(Op,Pre,Rem,Add,Constraints),
	all_true(Pre,Atual),
	Constraints,
	remove_all(Rem,Atual,A1),
	add_all(Add,A1,S).

all_true([],_).
all_true([X|Y],Atual) :-
	member(X,Atual),
	all_true(Y,Atual).

remove_all([],A,A).
remove_all([X|Y],Atual,Z) :-
	remove(X,Atual,A1),
	remove_all(Y,A1,Z).

remove(_,[],[]).
remove(X,[X|Y],L) :-
	remove(X,Y,L),!.
remove(X,[Y|Z],[Y|W]) :-
	remove(X,Z,W).

add_all(E,A,L) :-
	append(A,E,L).

imprime_caminho([]).
imprime_caminho([X|Y]) :-
	write(X),nl,
	imprime_caminho(Y).
