poolor(X,H) :- poolar(X,[],H,[]).
porlog(X,B4,H0,H) :- once(look(X,Y,B4)), leap(Y,H0,H).

look(X,       barph(var),_) :- var(X).
look(true,          skip,_).
look((X;Y),        or(L),_) :- or2List((X;Y),L0), shuffle(L0,L).
look((X,Y),     and(X,Y),_).
look(X,            do(X),_) :- predicate_property(X,built_in).
look(\+ X,        not(X),_).
look(X,     anybody(X,L),B4) :- clauses(X,L,B4).

leap(skip,        H, H).
leap(barph(Why),  H, H) :- format('% ERROR: ~p.~n',Why),fail.
%leap(do(X),      H, H) :- call(X).
leap(and(X,Y),    H0,H) :- poolor(X,H0,H1),  poolor(Y,H1,H).
leap(not(X),      H, H) :- \+ poolor(X,H,_).
leap(or(L),       H0,H) :- member(X,L), poolor(X,H0,H).
leap(anybody(X,L),H0,H) :- member(X/Body/Id,L), poolor(Body,[Id|H0],H).

or2List((X;Y),[X|Rest]) :- !, or2List(Y,Rest).
or2List(Y,    [Y]).

clauses(Head,Bodies,B4) :-
	findall(Head/Body/Id, clauses1(B4,Head,Body,Id), Bodies0),
	shuffle(Bodies0,Bodies).

clauses1(B4,Head,Body,Id) :- 
	var(B4) 
	-> clause(Head,Body,Id)
	|  clause(Head,Body,Id),
	   member(Id,B4).

shuffle([],[]).
shuffle([H|T], [One|Rest]) :- 
	oneLess([H|T], One, Less), 
	shuffle(Less,Rest).

oneLess(L,One,Less) :- length(L,N0),N is random(N0),oneLess1(N,L,One,Less). 

oneLess1(0,  [One|Less],One,Less).    
oneLess1(N0, [H|T],One, [H|Rest]) :-  N0>0, N is N0-1, oneLess1(N,T,One,Rest). 

car --> wheels, what.

wheels --> [chrome].
wheels --> [steel].

runs(N,G,I,O,Some) :- setof(One,runs1(N,G,I,O,One),Some).

runs1(N,G, I,O,W / I / O) :- N > 0, run(G, In,Out,W0),W is -1 * W0.
runs1(N,G, I,O,One      ) :- N > 1, N1 is N - 1, runs1(N1,Gs,I,O,Result).
	
