Ah, I see what you''re doing. A lot of people would say that''s a job for the search. I guess you and I are in the minority, because I like for my evaluation function to be as accurate as possible, so I try to evaluate these kinds of things statically as well.
If you''re using bitboards, there is are some interesting and little know algorithms that will do floodfilling and pathfinding kind of operations pretty efficiently, which might be useful for this kind of situation. The basic idea is that you do some shifting and ANDing of the bitboard to generate attacks, and you can do floodfills that "go around" squares that you specify.
As an example, you could generate attacks by floodfilling a "white rooks" bitboard in one direction, and passing in "empty squares" as the squares that are okay to fill through. Consider the following code:
typedef unsigned __int64 Bitboard;Bitboard UpAttacks (Bitboard b, Bitboard c){ b |= (b << 8) & c; c &= (c << 8); b |= (b << 16) & c; c &= (c << 16); b |= (b << 32) & c; return b << 8;}
If you had the bitboard that represented "all white rooks", and a bitboard that represented "empty squares", you could generate attacks in the upward direction by:
Bitboard upRookAttacks = UpAttacks(whiteRooks, emptySquares);
Or you could generate rook and queen attacks by:
Bitboard upRookAttacks = UpAttacks(whiteRooks|whiteQueens, emptySquares);
You can do similar fills left, right, down, and diagonally in all directions. For just generating attacks in one direction this isn''t particularly efficient. You can combine the UpAttacks() with DownAttacks() and the other directions to write a RookAttacks() function:
Bitboard RookAttacks (Bitboard rooks, Bitboard empty){ return UpAttacks(rooks, emtpy) | DownAttacks(rooks, empty) | LeftAttacks(rooks, empty) | RightAttacks(rooks, empty);}
Then it becomes trivial to find out which squares a rook can move to in 2 moves. Just do someting like:
Bitboard in1Move = RookAttacks(rooks, empty);
Bitboard in1Moves = RookAttacks(in1Move, empty);
Here''s some more code to play around with (below). ''b'' is usually the piece bitboard (whitePawns, blackRooks, etc.) although it could be anything that you want to generate attacks in some direction from. ''c'' is generally the squares you want to allow filling through, which is usually "empty squares". Sometimes you might want to generate a bitboard that is "safe empty squares" and you could use that to see if a king can reach a passed pawn, or whatever. This code assumes a1=0, b1=1, a2=8, etc.
// ----------// Pawn moves// ----------bitboard WhitePawnAttacks (bitboard b){return ((b << 7) & 0x7F7F7F7F7F7F7F7F) |((b << 9) & 0xFEFEFEFEFEFEFEFE);}bitboard BlackPawnAttacks (bitboard b){return ((b >> 7) & 0xFEFEFEFEFEFEFEFE) |((b >> 9) & 0x7F7F7F7F7F7F7F7F);}bitboard WhitePawnNonAttacks (bitboard b, bitboard c){b |= (b << 8) & c;c &= (c << 8);return b |= ((b & 0x0000000000FF0000) << 16) & c;}bitboard BlackPawnNonAttacks (bitboard b, bitboard c){b |= (b >> 8) & c;c &= (c >> 8);return b |= ((b & 0x0000FF0000000000) >> 16) & c;}// ------------// King Attacks// ------------bitboard KingAttacks (bitboard b){bitboard c = b;b |= (b >> 1) & 0x7F7F7F7F7F7F7F7F;b |= (b << 1) & 0xFEFEFEFEFEFEFEFE;b |= b << 8;b |= b >> 8;return b ^ c;}// --------------// Knight Attacks// --------------bitboard KnightAttacks (bitboard b){bitboard c = b;b ^= c;b |= (c >> 17) & 0x7F7F7F7F7F7F7F7F;b |= (c << 15) & 0x7F7F7F7F7F7F7F7F;b |= (c >> 15) & 0xFEFEFEFEFEFEFEFE;b |= (c << 17) & 0xFEFEFEFEFEFEFEFE;b |= (c >> 10) & 0x3F3F3F3F3F3F3F3F;b |= (c << 6) & 0x3F3F3F3F3F3F3F3F;b |= (c >> 6) & 0xFCFCFCFCFCFCFCFC;b |= (c << 10) & 0xFCFCFCFCFCFCFCFC;return b;}// ---------------------// Rank and file attacks// ---------------------bitboard UpAttacks (bitboard b, bitboard c){b |= (b << 8) & c;c &= (c << 8);b |= (b << 16) & c;c &= (c << 16);b |= (b << 32) & c;return b << 8;}bitboard DownAttacks (bitboard b, bitboard c){b |= (b >> 8) & c;c &= (c >> 8);b |= (b >> 16) & c;c &= (c >> 16);b |= (b >> 32) & c;return b >> 8;}bitboard LeftAttacks (bitboard b, bitboard c){c &= 0x7F7F7F7F7F7F7F7F;b |= (b >> 1) & c;c &= (c >> 1);b |= (b >> 2) & c;c &= (c >> 2);b |= (b >> 4) & c;c &= (c >> 4);return (b >> 1) & 0x7F7F7F7F7F7F7F7F;}bitboard RightAttacks (bitboard b, bitboard c){c &= 0xFEFEFEFEFEFEFEFE;b |= (b << 1) & c;c &= (c << 1);b |= (b << 2) & c;c &= (c << 2);b |= (b << 4) & c;c &= (c << 4);return (b << 1) & 0xFEFEFEFEFEFEFEFE;}bitboard RankFileAttacks (bitboard b, bitboard c){return UpAttacks(b,c) |DownAttacks(b,c) |LeftAttacks(b,c) |RightAttacks(b,c);}// ----------------// Diagonal attacks// ----------------bitboard DownLeftAttacks (bitboard b, bitboard c){c &= 0x7F7F7F7F7F7F7F7F;b |= (b >> 9) & c;c &= (c >> 9);b |= (b >> 18) & c;c &= (c >> 18);b |= (b >> 27) & c;c &= (c >> 27);return (b >> 9) & 0x7F7F7F7F7F7F7F7F;}bitboard UpLeftAttacks (bitboard b, bitboard c){c &= 0x7F7F7F7F7F7F7F7F;b |= (b << 7) & c;c &= (c << 7);b |= (b << 14) & c;c &= (c << 14);b |= (b << 21) & c;c &= (c << 21);return (b << 7) & 0x7F7F7F7F7F7F7F7F;}bitboard DownRightAttacks (bitboard b, bitboard c){c &= 0xFEFEFEFEFEFEFEFE;b |= (b >> 7) & c;c &= (c >> 7);b |= (b >> 14) & c;c &= (c >> 14);b |= (b >> 21) & c;c &= (c >> 21);return (b >> 7) & 0xFEFEFEFEFEFEFEFE;}bitboard UpRightAttacks (bitboard b, bitboard c){c &= 0xFEFEFEFEFEFEFEFE;b |= (b << 9) & c;c &= (c << 9);b |= (b << 18) & c;c &= (c << 18);b |= (b << 27) & c;c &= (c << 27);return (b << 9) & 0xFEFEFEFEFEFEFEFE;}bitboard DiagonalAttacks (bitboard b, bitboard c){return DownLeftAttacks(b,c) |UpLeftAttacks(b,c) |DownRightAttacks(b,c)|UpRightAttacks(b,c);}