:- use_module(checker).
:-use_module(library(time)).
:- consult(astar).

:- no_check([setof(_,_,_), is(_,_)]).
%%definisce lo stato del problema
%
type stato --> st(luogo,cliente,cliente,list(cliente)).

%%	definisce il predicato cliente con luogo di prelievo e consegna
%
type cliente --> c(incrocio,incrocio);v.
% %      definisce il predicato luogo, indicante la posizione dei due robot
%
type luogo --> at(incrocio,incrocio).
%%	definisce i nodi del problema di base (i vertici della griglia)
type incrocio --> in(int,int); casa1; casa2.
type list(X) --> [];[X|list(X)].
%%	stabilisce quali sono le mosse valide
pred mossa(stato,stato).
%%	stato finale del grafo
trovato(st(at(casa1,casa2),v,v,[])).
%%	lista dei nodi del problema vicini a quello corrente 
vicini(S,[]) :- trovato(S), !.
vicini(S,L) :-  setof(S1, mossa(S,S1),L), !; L=[].

%%	entrambi i taxi devono caricare un cliente
mossa(st(_,_,_,LC),st(at(A2,B2),c(A1,A2),c(B1,B2),LC1)):-
	member(c(A1,A2),LC),
	delete(LC,c(A1,A2),LCI),
	member(c(B1,B2),LCI),
	delete(LCI,c(B1,B2),LC1),
	A1 \= B1,
	A2 \= B2.
%%	entrambi i robot tornano a casa
mossa(st(at(_,_),_,_,[]),st(at(casa1,casa2),v,v,[])).
%%	primo robot va a casa per mancanza di clienti
mossa(st(_,_,_,[c(A,B)]),st(at(casa1,B),v,c(A,B),[])).
%%	secondo robot va a casa per mancanza di clienti
mossa(st(_,_,_,[c(A,B)]),st(at(B,casa2),c(A,B),v,[])).
%	viene calcolato il numero totale di mosse eseguite dai taxi per
%      servire tutti i clienti sulla mappa e ritornare alla propria base
%      
costo(at(AP,BP),st(at(A2,B2),c(A1,A2),c(B1,B2),_L),Costo) :-
      tragitto(A1,A2,RisA),
      tragitto(B1,B2,RisB),
      tragitto(AP,A1,RisR1),
      tragitto(BP,B1,RisR2),     
      Costo is RisA+RisB+RisR1+RisR2.
costo(at(AP,BP),st(at(casa1,casa2),v,v,_L),Costo) :-      
      tragitto(AP,casa1,RisA),      
      tragitto(BP,casa2,RisB),     
      Costo is RisB+RisA.
costo(at(_,BP),st(at(_,B2),v,c(B1,B2),_L),Costo) :-      
      tragitto(B1,B2,RisB),      
      tragitto(BP,B1,RisR2),     
      Costo is RisB+RisR2.
costo(at(AP,_),st(at(A2,_),c(A1,A2),v,_L),Costo) :-
      tragitto(A1,A2,RisA),
      tragitto(AP,A1,RisR1),           
      Costo is RisA+RisR1.
%%	h rappresenta l'euristica, data dai precorsi richiesti dai 
%%	clienti ancora da servire
h([],0).
h([c(A,B)|L],Res) :- h(L,Res1), tragitto(A,B,Dis), Res is Dis+Res1.
%%	funzione che calcola la distanza tra due incroci
tragitto(in(A1,B1),in(A2,B2),Ris):- A is abs(A1-A2), 
	B is abs(B1-B2),
	Ris is A+B.
%%	funzione tragitto per gestire casa1 e casa2 con 
%%	coordinate rispettivamente (6,1) e (1,5)
tragitto(A,A,0).
tragitto(casa1,in(A2,B2),Ris) :- tragitto(in(1,1),in(A2,B2),Ris).
tragitto(casa2,in(A2,B2),Ris) :- tragitto(in(1,5),in(A2,B2),Ris).
tragitto(casa2,casa1,Ris) :- tragitto(in(1,5),in(1,1),Ris).
tragitto(casa1,casa2,Ris) :- tragitto(in(1,1),in(1,5),Ris).
tragitto(in(A1,B1),casa2,Ris) :- tragitto(in(A1,1),in(B1,5),Ris).
tragitto(in(A1,B1),casa1,Ris) :- tragitto(in(A1,1),in(B1,1),Ris).

