0

I have a predicate list_moves(Move), that gives all the possible moves for a game. Then I have the following predicates :

find_best_move:-
    nb_setval(best,0),
    list_moves(NewMove),
    nb_getval(best,OldMove),
    better(OldMove,NewMove).

better(OldMove, NewMove):-
    NewMove > OldMove,
    nb_setval(best,NewMove), !.
better(_,_).

get_best_move(Move):-
    find_best_move,
    nb_getval(max,Move).

I want to get only one move when I call get_best_move(Move) : the best one. The problem is : I do get the best move, but I also get lots of other moves.

Exemple : Let's say I have the following moves in this order from list_moves(Move) (the bigger the value, the better the move) :
move1 : 0
move2 : 1
move3 : 2
move4 : 1
move5 : 2
move6 : 0

I will get the following result by calling get_best_move(Move) :
move1
move2
move3
move3
move3
move3

The thing is : I just want to get move3 once. I don't care about neither move1-2, nore the 3 other occurences of move3.

I think one solution could be to "wait" until the find_best_move call in get_best_move is finished, instead of doing nb_getval for each answer given by find_best_move.

How can I do this ? Is there an other solution ?

Scentle5S
  • 760
  • 1
  • 6
  • 13
  • 2
    Your program uses highly problematic built-ins resulting in code that is not reentrant. See the definition of [`call_nth/2`](http://stackoverflow.com/a/11400256/772868) how to perform this in a much cleaner manner. – false Jun 05 '15 at 23:50
  • Consider `setof(Nn,Np^(list_moves(Np),Nn is -Np),[Nn|_]), Nmax is -Nn`. – false Jun 05 '15 at 23:54

1 Answers1

0

Yes, of course, there is a solution. You are getting a list of results so you need to filter them by specific predicate or just take last one because you sort them in increasing order.

Prolog generates these solutions one by one. Sometimes we would like to have all the solutions to a query, and we would like them handed to us in a neat, usable, form. Prolog has three built-in predicates that do this: findall, bagof and setof. We need first to get all to list

?-  findall(X,get_best_move(Move))

should return list [move1, move2, move3, move3, move3, move3] then use last function

%%  last(?List, ?Last)
%
%   Succeeds when Last  is  the  last   element  of  List.  This
%   predicate is =semidet= if List is a  list and =multi= if List is
%   a partial list.
%
%   @compat There is no de-facto standard for the argument order of
%       last/2.  Be careful when porting code or use
%       append(_, [Last], List) as a portable alternative.

last([X|Xs], Last) :-
    last_(Xs, X, Last).

last_([], Last, Last).
last_([X|Xs], _, Last) :-
    last_(Xs, X, Last).

something like that

?- last(findall(X,get_best_move(Move)), Y)

I don't know which realisation you use, but this might help

sigrlami
  • 1,822
  • 1
  • 17
  • 35