grant wrote:I just thought of trying a quick calculation to get my TO square in my generate checks function, which also does not require magics.
I considered adding a function to selectively generate checks. The idea was to tabulate the squares where a piece of a certain type could deliver check, (what you call TO square), relative to King square, as a function of the current piece position (relative to King square). For sliders it would then have to be checked for each target if the rays King-TO and piece-TO were not blocked.
I grew less enthousiastic for this idea as I realized that a Queen can have 12 possible TO squares, while in the middle-game Queens often has less than 12 moves. So for a Queen it is probably more efficient to just generate the moves, and test if they check.
Now I think it is more efficient, in the process of King-safety determination, to differentially maintain a table where checks are possible (taken the Pawn shield into account). With good King safety, as the engine would maintain in most of the tree in the middle-game, there should be no non-capture slider checks amongst this, except on the back rank. So the problem would be reduced in most cases to figure out if there are Queen or Rook moves to the back rank, which is comparatively cheap to figure out by normal move generation for forward moves of these 3 pieces only.
grant wrote:I just thought of trying a quick calculation to get my TO square in my generate checks function, which also does not require magics.
I considered adding a function to selectively generate checks. The idea was to tabulate the squares where a piece of a certain type could deliver check, (what you call TO square), relative to King square, as a function of the current piece position (relative to King square). For sliders it would then have to be checked for each target if the rays King-TO and piece-TO were not blocked.
I grew less enthousiastic for this idea as I realized that a Queen can have 12 possible TO squares, while in the middle-game Queens often has less than 12 moves. So for a Queen it is probably more efficient to just generate the moves, and test if they check.
Now I think it is more efficient, in the process of King-safety determination, to differentially maintain a table where checks are possible (taken the Pawn shield into account). With good King safety, as the engine would maintain in most of the tree in the middle-game, there should be no non-capture slider checks amongst this, except on the back rank. So the problem would be reduced in most cases to figure out if there are Queen or Rook moves to the back rank, which is comparatively cheap to figure out by normal move generation for forward moves of these 3 pieces only.
It is easier than that if you use bitboards.
First, generate all possible queen moves from the square of the enemy king. Then generate all possible queen moves for your queen. And the two together. If it is non-zero, the bits that are set are squares where the queen can move to and give check to the enemy king.
I did a GenerateChecks() function for recent Crafty that does a similar trick for discovered checks as well, so it gets direct and discovered checks and never has to check to see if they really check the opponent.
bob wrote:It is easier than that if you use bitboards.
I know. But bitboards are slow as the area of the board, which scales quadratically with linear size, and I don't like that. Ray scans only scale as the linear size of the board.
So the purpose was to find the fastest way to do this for a mailbox board.
Yes, this is what I did in my previous GenerateChecks(), but I seem to have gone off the magics idea and only use them in GenerateCaptures(). Ironically.
For the queen, I let the GenerateCaptures() know when to save the attacks bitboard (certain plys in QS) which saves duplicating the calculation, though I may have to use magic to generate queen moves from the king to get my intersections here since this is not calculated anywhere else in the program.
For rooks giving check, I simply lookup the bitboard containing all the squares the rook has to pass over to capture the king (if you see what I mean), and AND it with ALLOccupied. If the result is zero, a non-capture check is possible and the TO square can be calculated (as above).
Same with bishops but at the moment I have to use intersecting bitboards to get my TO squares.
Grant
What about storing the bishop intersection squares of all pairs of squares in two arrays, one for each way of a bishop to go from A to B?
int diagIntersect1[64][64];
int diagIntersect2[64][64];
int to1, to2;
//
if ((allBishopTargetsFrom[oppKing] & allOccupied) == 0) {
to1 = diagIntersect1[from][oppKing];
to2 = diagIntersect2[from][oppKing];
}
Just as a quick idea. It takes some additional 32k of RAM and costs some memory accesses but should be quicker than the calculation mentioned above which requires branches.
int diagIntersect1[64][64];
int diagIntersect2[64][64];
int to1, to2;
//
if (!(allBishopTargets_1[from][oppKing] & allOccupied))
to1 = diagIntersect1[from][oppKing];
if (!(allBishopTargets_2[from][oppKing] & allOccupied))
to2 = diagIntersect2[from][oppKing];
If the bishop was not on the same colour square as the opponents king, then the first test would fail since the allBishopTargets bitboard would be set to 0xFFFFFFFFFFFFFFFF.
If the bishop was not on the same colour square as the opponents king, then the first test would fail since the allBishopTargets bitboard would be set to 0xFFFFFFFFFFFFFFFF.
Grant
Not sure you replied to me? I was referring to Edmund's post.
I don't understand the first condition at all ?!
If you like to waste 8KByte, why not immediately lookup 64*64 short or two byte arrays, where 0..63 per byte indicate valid intersection points, but 0xff or upper bits, no intersection.