0

I'm coding a board game similar to checkers using prolog and I have this function that tests random generated numbers. I want it to return the first instance that works but, for some reason, it fails after finding it because it tries to redo in what I can only guess is an attempt to find other suitable solutions.

%cell_status(+Board, +pos(X,Y), -Status)
cell_status([cell(X,Y,S)|_], pos(X,Y), Status) :-
    Status = S, !.                                           
cell_status([_|T], pos(X,Y), Status) :-
    cell_status(T, pos(X,Y), Status).

%select_random_piece(+Board, +Player, -X, -Y)
select_random_piece(Board, Player, X, Y) :- 
    random(0, 6, X_tmp),
    random(0, 5, Y_tmp),
    write('testing X: '), write(X_tmp), nl,
    write('testing Y: '), write(Y_tmp), nl,
    cell_status(Board, pos(X_tmp,Y_tmp), Status),
    (%if
        Status == Player ->
     %then
        X is X_tmp,
        Y is Y_tmp;
     %else
         select_random_piece(Board, Player, X_tmp, Y_tmp),
         X is X_tmp, Y is Y_tmp
    ).

I tried debugging using trace and verified that after cell_status exits with a correct Status value it tries to redo cell_status again and fails. I also checked that cell_status works fine by itself.

How can I use cut in order to stop it from finding other solutions? Or am I missinterpreting the problem?

TessellatingHeckler
  • 27,511
  • 4
  • 48
  • 87
  • I think the problem is that `select_random_piece` is calling itself, rather than just relying on backtracking. – brebs Dec 29 '22 at 11:44
  • I suggest you use the debugger and step through the execution to get an idea about where things go wrong. Hint: Make sure to verify that all calls makes sense given your mode (input/output) comments. – Per Mildner Dec 29 '22 at 12:17
  • @PerMildner I already did that as mentioned in the post. cell_status finds the correct cell and exits but then cell_status is recalled with the tag "redo" for some reason and it fails. – Diogo Costa Dec 29 '22 at 17:07
  • @brebs and how would I do that? – Diogo Costa Dec 29 '22 at 17:09
  • You can probably use `repeat` to solve this. – TA_intern Dec 29 '22 at 21:41
  • It would be less confusing to use `between` instead of `random`. The `->` block appears unnecessary. – brebs Dec 29 '22 at 22:02
  • @brebs Sorry I'm kind of new to logc programing, but how else will I simulate an *if else*? I only want to rerun the function until I have 1 valid solution, I looked into repeat and it does not seem to do what I want the program to do. – Diogo Costa Dec 30 '22 at 03:16

1 Answers1

0

Looks like this is all you need, for select_random_piece:

select_random_piece(Board, Player, X, Y) :- 
    between(0, 6, X),
    between(0, 5, Y),
    cell_status(Board, pos(X,Y), Player).

between creates choicepoints, for Prolog's inference engine to backtrack to, in search of a solution.

Let's avoid the complication of random, until fundamentals such as backtracking are understood.

brebs
  • 3,462
  • 2
  • 3
  • 12
  • Not a perfect solution as I needed a truly random choice for the bot to play. But it does work – Diogo Costa Dec 30 '22 at 22:35
  • You can then use `bagof` to assemble the list of valid "boards", then select one from the list at random. – brebs Dec 30 '22 at 22:41