% e.g.golorps(10,X,sentence(X,[])).
demo :- forall(between(1,10,_),demo1).

demo1 :-
	sentence(Sentence1,[]),
	golorp(sentence(Sentence2,[])),
	format('\n1 : ~p\n2 : ~p\n',[Sentence1,Sentence2]).
	

golorp(X) :- once(look(X,Y)), leap(Y).

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)) :- clauses(X,L).

leap(skip).
leap(barph(Why))   :- format('% ERROR: ~p.~n',Why),fail.
leap(do(X))        :- call(X).
leap(and(X,Y))     :- golorp(X),  golorp(Y).
leap(not(X))       :- \+ golorp(X).
leap(or(L))        :- member(X,L), golorp(X).
leap(anybody(X,L)) :- member(X/Body,L), golorp(Body).

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

clauses(X,Bodies) :-
	findall(X/Body, clause(X,Body), Bodies0),
	shuffle(Bodies0,Bodies).

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

oneLess(L0,Pruned,L) :-
    length(L0,N0),
    N is random(N0),
    oneLess1(N,L0,Pruned,L).

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