
%%%%% definizioni necessarie per la rappresentazione
%%%di un dominio

%%%%%%%%%%%%%%% direttive iniziali

:- [golog_swi].

%%% direttive discontiguous per i fluenti
:- discontiguous atR/2, at/3, free/1, ha/2.

%%%%%%%%%%% dichiarazione delle azioni primitive
primitive_action(vai(_,_)).
primitive_action(prendi(_)).
primitive_action(lascia(_)).

%%%%%% Restore suppressed situation arguments.
%% (un fatto per ogni fluente).
restoreSitArg(atR(X),S,atR(X,S)).
restoreSitArg(at(X,Y),S,at(X,Y,S)).
restoreSitArg(free,S,free(S)).
restoreSitArg(ha(X),S,ha(X,S)).

%%%%%%% Action precondition axioms
poss(vai(X,Y),S) :-
	atR(X,S), posto(Y), X \= Y.
poss(prendi(X),S) :-
	free(S), oggetto(X), atR(Y,S), at(X,Y,S).
poss(lascia(X),S) :-
	ha(X,S).

%%%%%%% Successor state axioms
% atR/2, at/3, free/1, ha/2
free(do(A,S)) :-
	A = lascia(_) ;
	free(S), A \= prendi(_).
ha(X,do(A,S)) :-
	A=prendi(X);
	ha(X,S), A\=lascia(X).
atR(X,do(A,S)) :-
	A = vai(_,X) ;
	atR(X,S), A \= vai(X,_).
at(X,Y,do(A,S)) :-
	A=lascia(X), atR(Y,S) ;
	at(X,Y,S), A\=prendi(X).

%%%%%%% definizione di eventuali predicati statici
oggetto(X) :- member(X,[libro,penna,pc]).
posto(X) :- member(X,[n1,n2,n3,n4]).
%%%% Initial situation
% atR/2, at/3, free/1, ha/2
atR(n1,s0).
at(libro,n1,s0).
at(penna,n2,s0).
at(pc,n3,s0).
free(s0).

proc(vaiprendere(X),
     ?(ha(X)) #
    star(pi(y, ?(at(X,y)) :
	   pi(z,vai(z,y)))) :
    star(pi(y,lascia(y))):
    prendi(X)).

%% versione ricorsiva
proc(portatutti(Loc),
     ?(all(x,oggetto(x) => at(x,Loc))) #
    pi(x,?(oggetto(x) & -at(x,Loc)) :
      vaiprendere(x) :
      pi(y,vai(y,Loc)) :
      lascia(x)) :
    portatutti(Loc)).

% versione con star
proc(portatutti_star(Loc),
     star(pi(x,?(oggetto(x) & -at(x,Loc)) :
	    vaiprendere(x) :
	    pi(y,vai(y,Loc)) :
	    lascia(x))) :
     ?(all(x,oggetto(x) => at(x,Loc)))).

% versione con while
proc(portatutti_while(Loc),
     while( %-all(x,oggetto(x) => at(x,Loc)),
	   some(x,oggetto(x) & -at(x,Loc)), 
	   pi(x,?(oggetto(x) & -at(x,Loc)) :
	     vaiprendere(x) :
	     pi(y,vai(y,Loc)) :
	     lascia(x)))).


%%% Sintassi del Golog
%%% sequenze di azioni: A1 : A2
%%% test: ?(Formula)
%%%         congiunzione: F & G
%%%         disgiunzione: F v G
%%%         implicazione: F => G
%%%         doppia implicazione: F <=> G
%%%         negazione: - F
%%%         quantificatore universale: all(V,F)
%%%         quantificatore esistenziale: some(V,F)
%%% scelta non deterministica di due azioni: A1 # A2
%%% if-then-else: if(Cond,A1,A2)
%%% ciclo: while(Cond,A)
%%% scelta non deterministica dell'argomento di un'azione:
%%%             pi(x,A)
%%% procedure: proc(Testa,Corpo)
%%%          parametri della procedura: variabili prolog


%%% esegui
% stampa la lista di azioni che eseguono una procedura
esegui(P) :- esegui(P,List), printlist(List).

esegui(P,Alist) :-
	do(P,s0,S), tolist(S,Alist).

tolist(s0,[]).
tolist(do(A,S),Alist) :-
	tolist(S,Tmp),
	append(Tmp,[A],Alist).

printlist([]).
printlist([X|Rest]) :-
	writeln(X),printlist(Rest).

