Problem with Negamax
Moderators: hgm, Rebel, chrisw
-
- Posts: 53
- Joined: Mon Sep 19, 2016 6:51 am
Re: Problem with Negamax
Thank You! How do I select the values of alpha and beta anyway, though?
-
- Posts: 27795
- Joined: Fri Mar 10, 2006 10:06 am
- Location: Amsterdam
- Full name: H G Muller
Re: Problem with Negamax
In the root alpha starts as -INFINITE and beta = +INFINITE. But like in any other node alpha is not constant, but increases to the the best score found so far. Other obtain an alpha and beta from their parent, alpha = -parentBeta and beta = -parentAlpha.
-
- Posts: 4052
- Joined: Thu May 15, 2008 9:57 pm
- Location: Berlin, Germany
- Full name: Sven Schüle
Re: Problem with Negamax
You can do it as described in the CPW.universecoder wrote:Thank You! How do I select the values of alpha and beta anyway, though?
-
- Posts: 53
- Joined: Mon Sep 19, 2016 6:51 am
Re: Problem with Negamax
The first and third are easily achievable. However, doing the second requires me to call isSquareAttacked on kingSquare(to check if the king is in check), making the entire thing redundant again! I thought this could be solved by calling isSquareAttacked() at the start in generateAllMoves(), is this True? If so, then isSquareAttacked will have to be called again for the entire LINE of moves.1. Moving the king can put it into check.
2. Moving when in check can miss to get out of check.
3. Capturing en passant can put the own king into check (if your king is on the same rank as both involved pawns, or if you start with a position that is unreachable from the initial opening position but has the enemy pawn that will be captured on the same diagonal as your king).
4. Moving a pinned piece can put your king into check.
The 4th seems to confuse me. To determine these pieces, I would have to loop in all directions emanating from the king, which take almost as much time as isSquareAttacked(). How does one overcome this problem. Do I maintain a list of pieces pinned to the king and update it incrementally?
Finally, I did perft without legality checking(to get an idea of the upper bound of speed I would get if I did the above) and I got ~ 1 million nps. Although you asked me not to worry about raw speed right now, are there any other optimizations possible? I implemented alphaBeta and I am not completely satisfied with the raw speed of perft. Still, are there any major improvements I can make(in perft)
A person on ##algorithms in freenode suggested that I incrementally maintain a list of attacked squares(I think this is unfeasible, since I would have to loop over and add constant amounts for various pieces, but I may be wrong).
-
- Posts: 53
- Joined: Mon Sep 19, 2016 6:51 am
Re: Problem with Negamax
Also, my notebook is 10 years old(Core 2 Duo and 2 GB RAM), does this matter much?
-
- Posts: 4052
- Joined: Thu May 15, 2008 9:57 pm
- Location: Berlin, Germany
- Full name: Sven Schüle
Re: Problem with Negamax
No, you simply save the result of isSquareAttacked(kingSquare) in a boolean variable and only pass that variable to the function that decides whether a particular move might be illegal.universecoder wrote:The first and third are easily achievable. However, doing the second requires me to call isSquareAttacked on kingSquare(to check if the king is in check), making the entire thing redundant again! I thought this could be solved by calling isSquareAttacked() at the start in generateAllMoves(), is this True? If so, then isSquareAttacked will have to be called again for the entire LINE of moves.1. Moving the king can put it into check.
2. Moving when in check can miss to get out of check.
3. Capturing en passant can put the own king into check (if your king is on the same rank as both involved pawns, or if you start with a position that is unreachable from the initial opening position but has the enemy pawn that will be captured on the same diagonal as your king).
4. Moving a pinned piece can put your king into check.
You determine the set of pinned pieces once per node, at about the same time when calling isSquareAttacked(kingSquare). Then you pass that set to the function mentioned above. A 64 bit number would be a good choice as a representation of the set since it can be maintained and tested efficiently.universecoder wrote:The 4th seems to confuse me. To determine these pieces, I would have to loop in all directions emanating from the king, which take almost as much time as isSquareAttacked(). How does one overcome this problem. Do I maintain a list of pieces pinned to the king and update it incrementally?
Once you have a legal move generator that uses the trick above, you can just return the number of legal moves at depth == 1 instead of making and unmaking all these moves at the last tree level. At that point it will make sense to report two different numbers: nodes per second (based on the number of nodes where perft() actually generated moves) and leaves per second (based on the number of leaves that are counted and form the result of perft()). NPS would then typically remain at a level of, say, 1 million (depending on CPU speed, compiler and settings of course) while LPS would go up significantly, maybe to 20 million. Of course LPS would decide about the time it takes to compute perft.universecoder wrote:Finally, I did perft without legality checking(to get an idea of the upper bound of speed I would get if I did the above) and I got ~ 1 million nps. Although you asked me not to worry about raw speed right now, are there any other optimizations possible? I implemented alphaBeta and I am not completely satisfied with the raw speed of perft. Still, are there any major improvements I can make(in perft)
It can be done. People have done it. But it would be quite a different approach from what you currently have. So you could write another engine based on that approach. If I were you I would stick with the current approach that seems to be simple enough to build a working engine upon.universecoder wrote:A person on ##algorithms in freenode suggested that I incrementally maintain a list of attacked squares(I think this is unfeasible, since I would have to loop over and add constant amounts for various pieces, but I may be wrong).
-
- Posts: 27795
- Joined: Fri Mar 10, 2006 10:06 am
- Location: Amsterdam
- Full name: H G Muller
Re: Problem with Negamax
Note that testing if there are pinned pieces is nearly the same thing as testing whether you are in check. If a ray scan away from your King hits a friendly piece, you just have to continue that ray scan a little bit further to see if there is an enemy slider behind it that looks your way. Or, in other words, when looking for pinned pieces, you get distant checks as a side effect for nearly free.universecoder wrote:However, doing the second requires me to call isSquareAttacked on kingSquare(to check if the king is in check), making the entire thing redundant again! I thought this could be solved by calling isSquareAttacked() at the start in generateAllMoves(), is this True? If so, then isSquareAttacked will have to be called again for the entire LINE of moves.
King moves are a pain, however. You would indeed have to test all of those for legality separately. But fortunately King moves make only a small fraction of your total number of moves.
When already in check, moves with non-royal pieces can be easily filtered. In case of a double check they will never be any good. And in case of a single checker they must land on the ray from king to (and including) the checker. This can be easily tested with the aid of an alignment and a distance table.