:- set_flag(output_options, [depth(full)]).
:- ['9_agentspeak'].
:- ['9_goldmining_sim'].

:- dynamic loc/2.
:- dynamic carries/2.
:- dynamic vis/1.
:- dynamic btr/1.

q :- desire(+(loc(gold,(1,4))),[]).

size(3,5).

btr([]).
loc(agent,(1,1)).
loc(obstacle,(1,3)).
loc(obstacle,(2,2)).
loc(obstacle,(2,3)).
loc(depot,(1,2)).
loc(gold,(1,4)).


%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

do(pick(gold)) :- loc(agent,X),
                  retract(loc(gold,X)),
                  assert(carries(agent,gold)),
                  cleanBtr.

do(move(X,Y)) :-  locUpdate(X,Y),
                  btr(List),
                  retract(btr(List)),
                  assert(btr([X|List])).

do(moveBack(X,Y)) :-  locUpdate(X,Y),
                      retract(btr([Y|List])),
                      assert(btr(List)).

do(drop(gold)) :- loc(agent,_),
                  retract(carries(agent,gold)),
                  cleanBtr.

locUpdate(X,Y) :- loc(agent,X), retract(loc(agent,X)),
                  assert(loc(agent,Y)), assert(vis(X)).

cleanBtr :- retract(btr(_)), assert(btr([])), retract_all(vis(_)).


%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

procedure(+(loc(gold,X)),P) :-
   loc(depot,Z),
   P = [!(loc(agent,X)), do(pick(gold)),
        !(loc(agent,Z)), do(drop(gold))].

procedure(+(!(loc(agent,X))),P) :- loc(agent,X), P=[].

procedure(+(!(loc(agent,X))),P) :-
    loc(agent,Y), not X=Y, adjacent(Y,Z),
    not loc(obstacle,Z), not vis(Z),
    manhattan(Y,X,D1), manhattan(Z,X,D2), D1>=D2,
    P = [do(move(Y,Z)), !(loc(agent,X))].

procedure(+(!(loc(agent,X))),P) :-
    loc(agent,Y), not X=Y, btr([Z|_]), 
    P = [do(moveBack(Y,Z)), !(loc(agent,X))].


%%%%%%%%%%%% auxiliary %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

agentSense(D) :- worldInfo(B,D), callAll(B).

callAll([]).
callAll([H|T]) :- call(H), callAll(T).

adjacent((X,Y),(Xp,Yp)) :- (Xp is X+1,Yp is Y;
                            Xp is X-1,Yp is Y;
                            Xp is X,Yp is Y+1;
                            Xp is X,Yp is Y-1),
                           size(M,N),
                           1=< Xp, Xp =< M,
                           1=< Yp, Yp =< N.

manhattan((X1,Y1),(X2,Y2),D) :- Xdist is abs(X1-X2),
                                Ydist is abs(Y1-Y2),
                                D is Xdist+Ydist.
