:- op(999,xfy,ror).
:- op(1,fx,any).
:- op(1,fx,one).

X ror Y  :- ror2l(X,L), rany((member(Z,L), Z)).

ror2l(X ror Y [X|T]) :- !, ror2l(Y,T).
ror2l(X [X]).

printPairs(L) :- nl,printPairs(L,'|    ',[]),nl.

printPairs(X,Pad,Padding) :- 
	once(printPairs1(X,Pad,Padding)).

printPairs1(X,_,_) :- 
	var(X),
	write('?').
printPairs1(X=Y,Pad,Padding) :- 
	nl,
	forall(member(P,Padding),print(P)),
	write(X), write(' = '),
	printPairs(Y,Pad,[Pad|Padding]).
printPairs1([],_,_). 
printPairs1([H|T],Pad,Padding) :- 
	printPairs(H,Pad,Padding), 
	printPairs(T,Pad,Padding).
printPairs1(X,_,_) :- write(X), write(' ').


some(N,X) :- between(1,N,_),one(X).
one(X)    :- once(rany(X)).
rany(X)    :-
	setof(R/X,(X,R is random(1000)),L),
	member(_/X,L).

map(P,L) :- findall(One,(member(One,L), call(P,One)),L).

term_expansion((class(X) :- Body),
	       (Head :- Neck,Body)) :-
	X =..[H|T],
	xpand(H=T,Head,Neck).

term_expansion(class(X),(Head :- Body)) :-
	X =..[H|T],
	xpand(H=T,Head,Body).

xpand(X=[H|T],Head,Body) :-
	xpand1([H|T],Vs,Body),
	Head =.. [X,Vs].

xpand1([X],[V],Z) :-
	xpand2(X,V,Z).
xpand1([X0,Y0|Z0],[V0|V],(X,Z)) :-
	xpand2(X0,V0,X),
	xpand1([Y0|Z0],V,Z).

xpand2(X0,Y,Z) :- once(what2do(X0,X)), doit(X,Y,Z).

what2do(X,                    err(X)) :- var(X).
what2do(What = V : C,err(What=V : C)) :- \+ ground((What,V,C)), \+ var(V).

what2do(What =V : any(C),choose(any,What,V,C)).
what2do(What =V : one(C),choose(one,What,V,C)).
what2do(What =V : C,     type(What,V,C)).
what2do(What    : any(C),choose(any,What,_,C)).
what2do(What    : one(C),choose(one,What,_,C)).
what2do(What    : C,     type(What,_,C)).
what2do(What = V,        true(What,V)).
what2do(What,            noop(What)).

doit(choose(any,What,V,C),What=V,rany(Y)) :- Y =.. [C,V].
doit(choose(one,What,V,C),What=V,once(rany(Y))) :- Y =.. [C,V].
doit(type(What,V,C),      What=V, Y) :- Y =.. [C,V].
doit(true(What,V),        What=V, true).
doit(noop(What),          What=_, true).

range(Min,Max,N) :- rany(between(Min,Max,N)).
repeatN(N,Goal) :- between(1,N,_), once(Goal).

thing(_).

class(family(
	 dad  : person
	,mum  : person
	,kids : children
)).

children(X) :- range(0,4,N), length(X,N), maplist(person1,X,X).
person1(X,X) :- person(X).

class(person(
	 fname: thing
	,gender : any aSex
	,lname: thing
        ,dob  : date
        ,job  : any aJob
)).

aSex(m).
aSex(f).

aJob(manager).
aJob(cook).
aJob(cleaner).

class(date(day = D : aDay,month=M: any aMonth,year =Y: aYear)) :-
	day(Y,M,D).


aYear(X) :- range(1970,2010,X).
aDay(X)  :- range(1,31,X).


aMonth(jan).
aMonth(feb).
aMonth(mar).

day(_,jan,D)  :- range(1,31,D).
day(_,mar,D) :- range(1,31,D).   
day(Y,feb,D) :-
	((0 is Y mod 4) -> Max = 29 ; Max=28),
	range(1,Max,D).

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

mission(X) :- 
