Iterating towards a goal I'm pretty proud of the following, but would welcome any comments from experts:

%% Provide with a Goal and it will iterate towards it.

guess(Goal, Res) :-
    guessIterate(Goal, [], Res).

guessIterate(Goal, Guesses, Res) :-
    makeGuess(Guess),
    check_against_guesses(Guess, Guesses),
    score(Guess, Goal, ThisScore),
    (
        %% if completely correct,...
        ThisScore == [4, 0]
    -&gt;
        Res = Guess
    ;
        write(Guess), write(' '), write(ThisScore),nl,
        NewGuesses = [guess(Guess, ThisScore) | Guesses],
        guessIterate(Goal, NewGuesses, Res)
    ).

/*
If this Guess is correct, it will pedict the right results for previous guesses
*/
check_against_guesses(_, []).
check_against_guesses(Guess, [guess(Code, Score) | TGuesses]) :-
    score(Code, Guess, Score),
    check_against_guesses(Guess, TGuesses).

makeGuess(Guess) :-
    Colours = [red, blue, green, yellow, orange, purple, pink],
    member(G1, Colours),
    member(G2, Colours),
    member(G3, Colours),
    member(G4, Colours),
    Guess = [G1, G2, G3, G4].   

/*
Score a guess, [#Black, #White], by first looking for exact matches - black - and then
look for inexaxct matches - white.
It is not possible for a guess of [...red, red...] to match twice with a
single 'red' in the Goal
*/

score(Guess, Goal, Res) :-
    pass1(Guess, Goal, [], Pass1Res),
    pass2(Guess, Pass1Res, Pass2Res),
    countUp(Pass2Res, [0,0], Res).

pass1(_, [], Acc, AccRev) :-
    reverse(Acc, AccRev).

pass1([HGuess | TGuess], [HGoal | TGoal], Acc, Res) :-
    (
        HGuess == HGoal
    -&gt;
        AccNew = [black  | Acc]
    ;
        AccNew = [HGoal | Acc]
    ),
    pass1(TGuess, TGoal, AccNew, Res).

%% check each Guess element with Goal and change Goal element to 'white' if there is a match
pass2([], Goal, GoalRev) :-
    reverse(Goal, GoalRev).

pass2([HGuess | TGuess], Goal, Res) :-
    pass2Helper(HGuess, Goal, [], ModifiedGoal),
    pass2(TGuess, ModifiedGoal, Res).

pass2Helper(_, [], Acc, AccRev) :-
    reverse(Acc, AccRev).

pass2Helper(Guess, [HGoal | TGoal], Acc, Res) :-
    (
        Guess == HGoal
    -&gt;
        reverse(TGoal, TGoalRev),
        %% Res = [white | TGoalRev]
        append(TGoalRev, [white | Acc], Res)
    ;
        AccNew = [HGoal | Acc],
        pass2Helper(Guess, TGoal, AccNew, Res)
    ).

countUp([], Acc, Acc).
countUp([HRes|TRes], [AccB, AccW|_], Res) :-
    (
        HRes == black
    -&gt;
        AccBNew is AccB + 1,
        countUp(TRes, [AccBNew, AccW], Res)
    ;
        (
            HRes == white
        -&gt;
            AccWNew is AccW + 1,
            countUp(TRes, [AccB, AccWNew], Res)
        ;
            countUp(TRes, [AccB, AccW], Res)
        )
    ).
Executive summary:


please_use_very_readable_names insteadOfUnreadableOneslikeInJava.
Use higher-order predicates.
Always consider using DCGs when describing lists. pass1 and pass2 can be simplified a lot with DCGS.
Use format/2 instead of multiple write/1 calls.




Examples:

Higher order predicate maplist/2, replacing 4 almost identical member/2 calls:

make_guess(Guess) :-
    length(Guess, 4),
    Colours = [red, blue, green, yellow, orange, purple, pink],
    maplist(list_member(Colours), Guess).

list_member(Ls, M) :- member(M, Ls).


Sample query and its result:

?- make_guess(Gs).
Gs = [red, red, red, red] ; 
Gs = [red, red, red, blue] ;
Gs = [red, red, red, green].


Further example, for counting the number if white elements with the higher-order predicate include/3:

list_num_white(Ls, N) :-
    include(=(white), Ls, Ws),
    length(Ws, N).


Sample query and its result:

?- list_num_white([white,black,white], N).
N = 2


Exercise: Generalize this by parametrizing the element, so that you can use list_element_count(Ls, black, N) and list_element_count(Ls, white, N).

Example for format/2: Instead of:

write(Guess), write(' '), write(ThisScore),nl


you can write:

format("~w ~w\n", [Guess,ThisScore])