        %  THE SIMPLIFIED ELEVATOR CONTROLLER 

% richiede l'uso di golog_swi, che viene caricato inizialmente

:- [golog_swi].
:- discontiguous currentFloor/2, on/2.
	
% Primitive control actions
primitive_action(up).   % Move elevator 1 floor up 
primitive_action(down). % Move elevator 1 floor down
primitive_action(open).        % Open elevator door.
primitive_action(close).       % Close elevator door.

% lower and higher floors
top(10).
bottom(-2).

% Preconditions for Primitive Actions.
poss(up,S) :-
	currentFloor(M,S), top(Top), M<Top.
poss(down,S) :-
	currentFloor(M,S), bottom(Bot), M > Bot.
poss(open,_).
poss(close,_).

% Successor State Axioms for Primitive Fluents.

% currentFloor(M,S) = the elevator is at floor S in situation S
currentFloor(M,do(A,S)) :-
	(A=up, currentFloor(N,S), M is N+1) ;
	(A=down, currentFloor(N,S), M is N-1) ;
	(currentFloor(M,S), not(A=up), not(A=down)).

% on(M,S): the call button M is on in situation S
on(M,do(_,S)) :- on(M,S), not(currentFloor(M,S)).

% Initial Situation. Call buttons: 3 and 5. The elevator is at floor 4.
on(3,s0).   on(5,s0).   currentFloor(4,s0).

% Restore suppressed situation arguments.
restoreSitArg(on(N),S,on(N,S)).
restoreSitArg(currentFloor(M),S,currentFloor(M,S)).

% Procedure down(n): move the elevator down n floors
proc(down(N),
     ?(N=0) #
    ?(N>0) : down :
    pi(m, ?(m is N-1) : down(m))).

% Procedure up(n): move the elevator up n floors
proc(up(N),
     ?(N=0) #
     ?(N>0) : up :
    pi(m, ?(m is N-1) : up(m))).

% Procedure goFloor(n): go to floor n
proc(goFloor(N),
     ?(currentFloor(N)) #
    pi(n1, ?(currentFloor(n1)) :
      if(n1<N, up, down))
    : goFloor(N)).

% procedure serve floor N and serve a floor
proc(serve(N), goFloor(N) : open : close).
proc(serveAfloor, pi(n, ?(on(n)) : serve(n))).

% main procedures: serve all floors with call buttons on
proc(main,
     while(some(x,on(x)),serveAfloor)).
 
/*
?- do(main,s0,S).
S = do(close, do(open, do(up, do(up, do(close, do(open, do(down, s0))))))) 
*/