Reputation: 582
I'm building a chess engine in Prolog. The alpha-beta from "prolog programing for artificial intelligence" is not depth limited. Since it's not possible to search the whole tree in chess I'm trying to modify the code from the book to be depth limited but it's not working properly.
here is the book code:
alphabeta(Pos, Alpha, Beta, GoodPos, Val) :-
moves(Pos, PosList), !,
boundedbest( PosList, Alpha, Beta, GoodPos, Val)
;
get_pos_value(Pos,Val). % static value of Pos
boundedbest([Pos | PosList], Alpha, Beta, GoodPos, GoodVal) :-
alphabeta( Pos, Alpha, Beta, _, Val),
goodenough(PosList, Alpha, Beta, Pos, Val, GoodPos, GoodVal).
goodenough([],_,_,Pos, Val, Pos, Val) :- !. % no other candidate
goodenough(_, Alpha, Beta, Pos, Val, Pos, Val) :-
min_to_move(Pos), Val > Beta, !; % Maximizer attained upper bound
max_to_move(Pos), Val < Alpha, !. % Minimizer attained lower bound
goodenough( PosList, Alpha, Beta, Pos, Val, GoodPos, GoodVal) :-
newbounds( Alpha, Beta, Pos, Val, NewAlpha, NewBeta), % Refine bounds
boundedbest(PosList, NewAlpha, NewBeta, Pos1, Val1),
betterof( Pos, Val, Pos1, Val1, GoodPos, GoodVal).
newbounds(Alpha, Beta, Pos, Val, Val, Beta) :-
min_to_move(Pos), Val > Alpha, !. % Mazximizer increased lower bound
newbounds(Alpha, Beta, Pos, Val, Alpha, Val):-
max_to_move(Pos), Val < Beta, !. % Minimizer decreased upper bound
newbounds( Alpha, Beta, _,_,Alpha, Beta). % otherwise bounds unchanged.
betterof(Pos, Val, Pos1, Val1, Pos, Val) :- % Pos better than Pos1
min_to_move(Pos), Val > Val1, !;
max_to_move(Pos), Val < Val1, !.
betterof(_,_,Pos1,Val1,Pos1,Val1). % otherwise Pos 1 better
My attempts to modify it to be depth limited are :
alphabeta(Pos, Alpha, Beta, Pos, Val, 0) :- % max depth of search recieved
get_pos_value(Pos,Val). % static value of Pos
alphabeta(Pos, Alpha, Beta, GoodPos, Val, Depth) :-
Depth > 0,
moves(Pos, PosList), !,
boundedbest( PosList, Alpha, Beta, GoodPos, Val,Depth).
alphabeta(Pos, Alpha, Beta, Pos, Val, Depth) :-
Depth > 0,
get_pos_value(Pos,Val).
boundedbest([Pos | PosList], Alpha, Beta, GoodPos, GoodVal,Depth) :-
Depth is Depth - 1,
alphabeta( Pos, Alpha, Beta, _, Val,Depth1),
goodenough(PosList, Alpha, Beta, Pos, Val, GoodPos, GoodVal).
goodenough([],_,_,Pos, Val, Pos, Val) :- !. % no other candidate
goodenough(_, Alpha, Beta, Pos, Val, Pos, Val) :-
min_to_move(Pos), Val > Beta, !; % Maximizer attained upper bound
max_to_move(Pos), Val < Alpha, !. % Minimizer attained lower bound
goodenough( PosList, Alpha, Beta, Pos, Val, GoodPos, GoodVal) :-
newbounds( Alpha, Beta, Pos, Val, NewAlpha, NewBeta), % Refine bounds
boundedbest(PosList, NewAlpha, NewBeta, Pos1, Val1,_),
betterof( Pos, Val, Pos1, Val1, GoodPos, GoodVal).
newbounds(Alpha, Beta, Pos, Val, Val, Beta) :-
min_to_move(Pos), Val > Alpha, !. % Mazximizer increased lower bound
newbounds(Alpha, Beta, Pos, Val, Alpha, Val):-
max_to_move(Pos), Val < Beta, !. % Minimizer decreased upper bound
newbounds( Alpha, Beta, _,_,Alpha, Beta). % otherwise bounds unchanged.
betterof(Pos, Val, Pos1, Val1, Pos, Val) :- % Pos better than Pos1
min_to_move(Pos), Val > Val1, !;
max_to_move(Pos), Val < Val1, !.
betterof(_,_,Pos1,Val1,Pos1,Val1). % otherwise Pos 1 better
I would appreciate any help.
Upvotes: 1
Views: 717
Reputation: 9378
You have a typo in your code. And more importantly, you have a typo in your code that SWI-Prolog found and diagnosed for you. Do not ignore its warnings.
Look:
Warning: /home/isabelle/chess.pl:1:
Singleton variables: [Alpha,Beta]
Warning: /home/isabelle/chess.pl:11:
Singleton variables: [Alpha,Beta]
Warning: /home/isabelle/chess.pl:16:
Singleton variables: [Depth1]
Warning: /home/isabelle/chess.pl:40:
Singleton variables: [Pos1]
Specifically, in this clause starting on line 16:
boundedbest([Pos | PosList], Alpha, Beta, GoodPos, GoodVal,Depth) :-
Depth is Depth - 1,
alphabeta( Pos, Alpha, Beta, _, Val,Depth1),
goodenough(PosList, Alpha, Beta, Pos, Val, GoodPos, GoodVal).
your use of Depth1
shows that you seem to understand that a new value needs to be computed and passed into the recursion. But you forgot to use this variable on the preceding line:
Depth is Depth - 1,
this should use Depth1
in the left hand side.
It is a mistake to even try to test code that has singleton warnings, since singleton warnings are often an indication of very serious bugs. This is the case here. When you see a singleton warning, the first thing you should do is to understand and fix it---any other interaction with the program is likely meaningless.
It is true that some of these warnings are "benign": The warnings for the clause on the first line do not seem to indicate bugs in that clause. Maybe you have seen some of these warnings and decided that they are harmless. The exact opposite is the case: Accepting such "spurious" singleton warnings means that you risk serious warnings slipping in.
(I haven't tested the corrected program since it's understandably incomplete.)
Upvotes: 3