I just had a look to Roland Chastain's Moustique sources based on JS Schach by Jürgen Schlottke from the early 90s, written in Turbo Pascal.
I found the maxwertung aka bestEval search routine interesting, direct recursion without negamax, suboptimal approximation of alpha-beta.
Eval is called inside the move loop - there seems to be no q-search. For the maxplayer, the alpha-beta semantic is reversed.
What are the primary deficits of this approach?
Gerd Isenberg wrote: ↑Wed Oct 21, 2020 10:50 amWhat are the primary deficits of this approach?
Without QS, I think the horizon effect will be much more prominent - unless QS is hidden in eval().
Sure, It seems I missed an extra condition that the move was not a capture in the pseudo code to decide about eval (material only) or recursive search call.
Some programs (such as the Jocly generic AI for chess variants) do indeed use SEE on the last-moved piece as eval term. This cures the worst horizon effects, as it thwarts the strategy of manoeuvring such (often by sacrificing minor material to force the opponent to use his ply for recapture, lest the sacrifice would turn into a gain) that you can capture a fat piece on the last move before the horizon through a bad capture.
It is actually a pretty good way to handle variants where a capture search tends to explode, such as Tenjiku Shogi. In the latter quiet manoeuvring with a Fire Demon (a weapon of mass destruction) often gains much more than capturing individual pieces, so it makes sense to keep QS as light as possible there, so that the full-width search can be deeper.
As to avoiding negamax: it requires all code that appears in duplicate to be split into separate sections for max- and the min-player, differing only in the < and > operators. For a very basic search this is not really a problem (the required single conditional is easily predicted). But in principle isuch duplication makes the code more difficult to maintain, as there is no guarantee both sections will always remain equivalent. And in more advanced search, where there are more score-based decisions, such duplications woul pop up all over the place.
hgm wrote: ↑Wed Oct 21, 2020 11:21 am
Some programs (such as the Jocly generic AI for chess variants) do indeed use SEE on the last-moved piece as eval term. This cures the worst horizon effects, as it thwarts the strategy of manoeuvring such (often by sacrificing minor material to force the opponent to use his ply for recapture, lest the sacrifice would turn into a gain) that you can capture a fat piece on the last move before the horizon through a bad capture.
Yes, that is not the case here, it calls pure material eval inside the move loop only if the made move was not a capture (if I understand the Pascal code correctly). https://github.com/rchastain/moustique/ ... e.pas#L409
Gerd Isenberg wrote: ↑Wed Oct 21, 2020 10:50 am
I found the maxwertung aka bestEval search routine interesting, direct recursion without negamax, suboptimal approximation of alpha-beta.
Hello! Thank you for the discussion and for your careful reading of Jürgen Schlottke's code. I liked this program, because it plays very fast and gives the impression of playing quite well, with a funny style (IMHO). Sorry, I have nothing more interesting to say.
Last edited by Roland Chastain on Wed Oct 21, 2020 11:37 am, edited 1 time in total.
Gerd Isenberg wrote: ↑Wed Oct 21, 2020 11:14 amSo I mean deficits of the approach with passing one bound only and the cut-off condition.
I find the labels pretty confusing because alpha and beta seem to have reversed functionality. In conventional terminology, alpha is always initialised to the worst case value in every node, not to the -beta from the parent node. In all paths except the leftmost one, I think this leads to a larger search tree.
Gerd Isenberg wrote: ↑Wed Oct 21, 2020 11:14 amSo I mean deficits of the approach with passing one bound only and the cut-off condition.
I find the labels pretty confusing because alpha and beta seem to have reversed functionality. In conventional terminology, alpha is always initialised to the worst case value in every node, not to the -beta from the parent node. In all paths except the leftmost one, I think this leads to a larger search tree.
if FActive = AColor then
begin
if LValue > LBeta then
LBeta := LValue;
if LBeta >= AAlpha then
LStop := TRUE;
end else
begin
if LValue < LBeta then
LBeta := LValue;
if LBeta <= AAlpha then
LStop := TRUE;
end;
Gerd Isenberg wrote: ↑Wed Oct 21, 2020 10:50 am
I found the maxwertung aka bestEval search routine interesting, direct recursion without negamax, suboptimal approximation of alpha-beta.
Hello! Thank you for the discussion and for your careful reading of Jürgen Schlottke's code. I liked this program, because it plays very fast and gives the impression of playing quite well, with a funny style (IMHO). Sorry, I have nothing more interesting to say.
Hi Roland,
thanks for hosting and retouching those interesting sources. Fixed depth of 3 without iterative deepening and max depth 5 for captures should be quite fast. And at that depth the deficits missing deep cutoffs is not that important.