%   File   : RANDOM.PL
%   Author : R.A.O'Keefe
%   Updated: 1 October 1984
%   NIP version: 13 May 1987
%   Purpose: Random number generator.

%   given an integer N >= 1, random(N, I) unifies I with a random
%   integer between 0 and N - 1.

random(N, I) :-
	(	recorded(seed,[A0,A1,A2],Key)
		->	erase(Key)
	;
			A0 = 3172, A1 = 9814, A2 = 20125
	),
	B0 is (A0*171) mod 30269,
	B1 is (A1*172) mod 30307,
	B2 is (A2*170) mod 30323,
	record(seed,[B0,B1,B2],_),
	R is A0/30269 + A1/30307 + A2/30323,
	I is trunc((R - trunc(R)) * N).

%	The next bit: K R Johnson, 13-5-87
%	Restart the random sequence from the beginning

randomise :-
	(	recorded(seed,[_,_,_],Key)
		->	erase(Key)
		;	true
	),
	record(seed, [3172,9814,20125], _).

%	Instantiate the seeds to your own favourite value

randomise(Seed) :-
	integer(Seed),
	Seed > 0,
	(	recorded(seed,[_,_,_], Key)
		->	erase(Key)
		;	true
	),
	S0 is Seed mod 30269,
	S1 is Seed mod 30307,
	S2 is Seed mod 30323,
	record(seed,[S0,S1,S2],_).

%   given an non-empty List, random(List, Elem, Rest) unifies Elem with
%   a random element of List and Rest with the other elements.

random(List, Elem, Rest) :-
	length(List, N),
	N > 0,
	random(N, I),
	nth0(I, List, Elem, Rest).


%   rand_perm(List, Perm) unifies Perm with a random permutation
%   of List.  What good this may be I'm not sure, and there's bound
%   to be a more efficient way of doing it.  Oh well.

rand_perm([], []).
rand_perm([H1|T1], [H2|T2]) :-
	random([H1|T1], H2, T3),
	rand_perm(T3, T2).