% Peg solitaire puzzle
% Author: LP Class
% Brute force

/*
Board consiste of list peg(C) and hole(C) for
places C.  Possible jumps are between(C1,C2,C3).
*/

% test(N) -- print the number of possible N moves
% Uses GNU Prolog global variables.
test(N) :-
	g_assign(count, 0),
	solve(N),
	g_inc(count),				% not affected by backtracking
	fail.
test(N) :-
	g_read(count, K),
	format("At ~p, ~p solutions\n", [N,K]).

% solve(N) -- make N moves from initial state
solve(N) :-
	init(State0),
	moves(N, State0).

% moves(N, State) -- make N moves from State.
moves(0, _).
moves(N, State1) :-
	N > 0,
	move1(State1,State2),
	N1 is N-1,
	moves(N1, State2).

% move1(State1, State2) -- make 1 move from State1 to reach State 2
move1(State1,State4) :-
	( between(A,B,C) ; between(C,B,A) ),
	swap(State1, peg(A), State2),
	swap(State2, peg(B), State3),
	swap(State3, hole(C), State4).

% swap(State1, peg(A), State2) flips peg(A) to hole(A)
% swap(State1, hole(A), State2) flips hole(A) to peg(A)
% in State1, returning State2.
swap([peg(A)|State], peg(A), [hole(A)|State]).
swap([hole(A)|State], hole(A), [peg(A)|State]).
swap([Place|State1], Place0, [Place|State2]) :-
	swap(State1, Place0, State2).

% init(State0) if State0 is the initial state
init([                peg(20),peg(30),peg(40),
                      peg(21),peg(31),peg(41),
      peg(02),peg(12),peg(22),peg(32),peg(42),peg(52),peg(62),
      peg(03),peg(13),peg(23),hole(33),peg(43),peg(53),peg(63),
      peg(04),peg(14),peg(24),peg(34),peg(44),peg(54),peg(64),
                      peg(25),peg(35),peg(45),
                      peg(26),peg(36),peg(46)                  ]).

% between(A,B,C) if A-B-C is a possible jump up or right
% if lower left corner is 00 and upper right corner is 66.
between(20,30,40).
between(20,21,22).
between(30,31,32).
between(40,41,42).
between(21,31,41).
between(21,22,23).
between(31,32,33).
between(41,42,43).
between(02,12,22).
between(02,03,04).
between(12,22,32).
between(12,13,14).
between(22,32,42).
between(22,23,24).
between(32,42,52).
between(32,33,34).
between(42,52,62).
between(42,43,44).
between(52,53,54).
between(62,63,64).
between(03,13,23).
between(13,23,33).
between(23,33,43).
between(23,24,25).
between(33,43,53).
between(33,34,35).
between(43,53,63).
between(43,44,45).
between(04,14,24).
between(14,24,34).
between(24,34,44).
between(24,25,26).
between(34,44,54).
between(34,35,36).
between(44,54,64).
between(44,45,46).
between(25,35,45).
between(26,36,46).
