lj(Agent, AnsStore, Ans) :- lj(Agent, 1, X-X, AnsStore, Ans-1, _Flag).

lj(1, Store, Queue, AnsStore, Ans, Flag) :- 
   check(Flag, Store, Queue, AnsStore, Ans).

lj(X:T, Store, Hd-1, AnsStore, Ans, nodeadlock) :- 
    eval(T, T1),
    lj(Hd, (X:T1,Store), Q-Q, AnsStore, Ans, nodeadlock).

lj((A,B), Store, Queue,  AnsStore, Ans, Flag) :-
   lj(A, Store,  Queue,  Store1, Ans1, Flag),
   lj(B, Store1, Ans1, AnsStore, Ans, Flag).

lj(X^A, Store, Queue, AnsStore, Ans, Flag) :-
   new(X, _NewX, A, A1), 
   lj(A1, Store, Queue, AnsStore, Ans, Flag).

lj((C -> A), Store, Queue, AnsStore, Ans, Flag) :-
   ask(C) -> lj(A, Store, Queue, AnsStore, Ans, nodeadlock) 
            ; check(Flag, Store, Queue, AnsStore, Ans).

lj((X:M '-o' A), Store, Queue, AnsStore, Ans, Flag) :-
   match(X, M, Store, Store1)
    -> (lj(A, Store1, Queue, AnsStore, Ans, nodeadlock))
      ; (Queue = Head - ((X:M '-o' A), Tail), 
         check(Flag, Store, Head-Tail, AnsStore, Ans)). 

lj(! Clause, Store, Head - (!Clause, Tail), AnsStore, Ans, Flag) :-
   copy(Clause, X:M '-o' A),
   match(X, M, Store, Store1)
    -> lj(A, Store1, Head-Tail, AnsStore, Ans, nodeadlock) 
      ; check(Flag, Store, Head-Tail, AnsStore, Ans).

check(deadlock, Store, Queue, AnsStore, Ans) :- !, 
    Ans=Queue, AnsStore=Store.
check(nodeadlock, Store, Head-1, AnsStore, Ans) :-
    lj(Head, Store, X-X, AnsStore, Ans, _Flag).

ask(C):- call(C).

