New-ish engine coder, would appreciate if someone could look at my code and point me in the right directions
Moderators: hgm, Rebel, chrisw
-
- Posts: 12
- Joined: Sat Jun 20, 2020 5:45 pm
- Full name: Alex Baker
Re: New-ish engine coder, would appreciate if someone could look at my code and point me in the right directions
Actually, even if that is a problem, I don't think it's my main problem because when I mess with that I get completely wrong evaluations, rather than the slightly wrong evaluations I get with my initial code. Anything that doesn't affect the top level much but picks wrong moves further down the line is surely to do with my quiescence search, but I can't for the life of me figure out what's wrong with it - it's literally just book code.
-
- Posts: 4052
- Joined: Thu May 15, 2008 9:57 pm
- Location: Berlin, Germany
- Full name: Sven Schüle
Re: New-ish engine coder, would appreciate if someone could look at my code and point me in the right directions
The +abm() must be correct. In Negamax you negate the result of searching a child node where it was the opponent's turn. But in mtdf() you call abm() still at root so there is nothing to negate yet. Your Negamax happens inside of abm() only.
Does your static eval return a score from the viewpoint of the side to move, or always of White? The latter would be wrong for Negamax.
Does your static eval return a score from the viewpoint of the side to move, or always of White? The latter would be wrong for Negamax.
Sven Schüle (engine author: Jumbo, KnockOut, Surprise)
-
- Posts: 12
- Joined: Sat Jun 20, 2020 5:45 pm
- Full name: Alex Baker
Re: New-ish engine coder, would appreciate if someone could look at my code and point me in the right directions
It's just from the perspective of the side to move - in my code it's pos.analysisPlayerSven wrote: ↑Thu Jul 02, 2020 9:58 pm The +abm() must be correct. In Negamax you negate the result of searching a child node where it was the opponent's turn. But in mtdf() you call abm() still at root so there is nothing to negate yet. Your Negamax happens inside of abm() only.
Does your static eval return a score from the viewpoint of the side to move, or always of White? The latter would be wrong for Negamax.
-
- Posts: 12
- Joined: Sat Jun 20, 2020 5:45 pm
- Full name: Alex Baker
Re: New-ish engine coder, would appreciate if someone could look at my code and point me in the right directions
Interestingly, now that I've changed it to +abm in the mtdf function, I'm pretty much getting all the right moves in the lines, but they're all evaluating to the same thing at the top level (whatever currentEstimate is)
Seems to be caused by this line:
But if I remove that, all the random moves come back
edit: changed it to and everything seems to work. I get different moves (look slightly worse) but I get the right eval!
MTDF is obviously not working as it should be though - I still go through about 150 MTDF passes at each depth, and also when I add null moves back in I start getting weird moves further down the lines again (though largely the right moves at the top), and the only difference between abm in the null move call and the normal call is the window (-beta, -beta+1 instead of -beta, -alpha) so I guess it's something to do with that - also makes sense for the mtdf function behaving strangely. Also all my top level moves that get cut early get evaluations equal to the currentEstimate in mtdf at the time they're evaluated.
Seems to be caused by this line:
Code: Select all
if(stand_pat >= beta) return beta;
edit: changed it to
Code: Select all
if(stand_pat >= beta) return stand_pat;
MTDF is obviously not working as it should be though - I still go through about 150 MTDF passes at each depth, and also when I add null moves back in I start getting weird moves further down the lines again (though largely the right moves at the top), and the only difference between abm in the null move call and the normal call is the window (-beta, -beta+1 instead of -beta, -alpha) so I guess it's something to do with that - also makes sense for the mtdf function behaving strangely. Also all my top level moves that get cut early get evaluations equal to the currentEstimate in mtdf at the time they're evaluated.
-
- Posts: 4052
- Joined: Thu May 15, 2008 9:57 pm
- Location: Berlin, Germany
- Full name: Sven Schüle
Re: New-ish engine coder, would appreciate if someone could look at my code and point me in the right directions
In mtfd(), when changing -abm(...) into +abm(...), did you also remove the color switching in the function call (1-.....)?
Sven Schüle (engine author: Jumbo, KnockOut, Surprise)
-
- Posts: 4052
- Joined: Thu May 15, 2008 9:57 pm
- Location: Berlin, Germany
- Full name: Sven Schüle
Re: New-ish engine coder, would appreciate if someone could look at my code and point me in the right directions
Furthermore, I do not fully understand your code regarding the side to move and the viewpoint of the static evaluation. I see three terms:
1) pos.analysisPlayer, which seems to be the side to move at the root node (but why do you still need to maintain that, after having switched from minimax to negamax?),
2) pos.board[PLAYER_TURN], which looks like the side to move in the current position (changed by making a move), and
3) player, a parameter of your abm() function which should always have the same value as pos.board[PLAYER_TURN] and is switched in each recursive call (so why maintaining both?).
In my view it would be sufficient to just keep one of those three, which would keep the code simple and consistent.
But apart from that, are you really sure that the expression
always returns the static evaluation score from the viewpoint of "player"? If I am not totally off the road this would only be true if "pos.score" would be a score always from the viewpoint of the opponent of "pos.analysisPlayer", which sounds a bit fishy to me ... but I do not know your code so I just keep asking questions
1) pos.analysisPlayer, which seems to be the side to move at the root node (but why do you still need to maintain that, after having switched from minimax to negamax?),
2) pos.board[PLAYER_TURN], which looks like the side to move in the current position (changed by making a move), and
3) player, a parameter of your abm() function which should always have the same value as pos.board[PLAYER_TURN] and is switched in each recursive call (so why maintaining both?).
In my view it would be sufficient to just keep one of those three, which would keep the code simple and consistent.
But apart from that, are you really sure that the expression
Code: Select all
(player != pos.analysisPlayer)?pos.score:-pos.score
Sven Schüle (engine author: Jumbo, KnockOut, Surprise)