I think that there are some unefficient things in movei about the pawn structure because I have bitboards that I update during makemove and
I have also global arrays that I update during making moves.
I think to get rid of the arrays and calculate information when I need it
based on bitboards but I am not sure what is the good way to calculate things based on bitboard
Today I have
numfilwhitepawns that give me the number of white pawns in file i in
one global array and I also have some bitboards like
pawnBB[LIGHT] that is 64 bit number that tell me the squares of the pawns when A1=0 A8=7 H8=63.
both type of data are updated when I make moves and I think that it may be better to have less variables and calculate part of the data from bitboards.
The question is how I get in an efficient way the number of pawns in one file or maybe it is not important because I can get information like that from the pawn hash(the only question is if probing the hash is not going to be more expensive in case that I store more information there and today I store only the part of evaluation that is dependent only on pawn structure in the pawn hash table).
Note that there are cases when I only want to know if the number of pawns in one file is positive
I think that I can use
if ((FILEA<<fil0(j))&pawnBB[LIGHT])
instead of using
// if (numfilwhitepawns[fil0(j)]>0)
fil0(j) is 0 for file a,1 for file b,...7 for file h
Uri
how to claculate with bitboard in fast way
Moderators: hgm, Rebel, chrisw
-
- Posts: 10298
- Joined: Thu Mar 09, 2006 12:37 am
- Location: Tel-Aviv Israel
-
- Posts: 12541
- Joined: Wed Mar 08, 2006 8:57 pm
- Location: Redmond, WA USA
Re: how to claculate with bitboard in fast way
Sure. There are lots of easy tricks for pawns using bitmaps.
You can also do attacks for all pawns at once, and using the same method find out if your pawns are defending one another or are isolated.
Consider:
void generateWhitePawnCaptures(ChessPosition * position, moveStack * stack)
{
int orig,
dest;
move m;
BitBoard attackedSquares;
if (position->enpassant != NO_ENPASSANT) {
attackedSquares = position->blackPieces | mask[position->enpassant];
} else {
attackedSquares = position->blackPieces;
}
pieceMap = position->whitePawns;
pieceMap &= 0x7F7F7F7F7F7F7F7F;
attackMap = (pieceMap << 9) & attackedSquares;
while (attackMap) {
dest = LSB(attackMap);
orig = dest - 9;
attackMap ^= mask[dest];
m.orig = orig;
m.dest = dest;
if (ROW(dest) == 7) {
m.promotion = QUEEN;
pushMove(m, stack);
m.promotion = KNIGHT;
pushMove(m, stack);
m.promotion = BISHOP;
pushMove(m, stack);
m.promotion = ROOK;
pushMove(m, stack);
} else {
m.promotion = EMPTY;
pushMove(m, stack);
}
}
if (position->enpassant != NO_ENPASSANT) {
attackedSquares = position->blackPieces | mask[position->enpassant];
} else {
attackedSquares = position->blackPieces;
}
pieceMap = position->whitePawns;
pieceMap &= 0xFEFEFEFEFEFEFEFE;
attackMap = (pieceMap << 7) & attackedSquares;
while (attackMap) {
dest = LSB(attackMap);
orig = dest - 7;
attackMap ^= mask[dest];
m.orig = orig;
m.dest = dest;
if (ROW(dest) == 7) {
m.promotion = QUEEN;
pushMove(m, stack);
m.promotion = KNIGHT;
pushMove(m, stack);
m.promotion = BISHOP;
pushMove(m, stack);
m.promotion = ROOK;
pushMove(m, stack);
} else {
m.promotion = EMPTY;
pushMove(m, stack);
}
}
}
The same trick can also be used to tell if your pawn structure needs help. For instance, here:
[D]5k2/8/6n1/2PP4/8/PP1K4/8/8 w - -
None of the pawns support each other. By doing the same attack trick but checking for your own pawns you will see that they don't support each other, but it is easy to make them diagonal.
You can also do attacks for all pawns at once, and using the same method find out if your pawns are defending one another or are isolated.
Consider:
void generateWhitePawnCaptures(ChessPosition * position, moveStack * stack)
{
int orig,
dest;
move m;
BitBoard attackedSquares;
if (position->enpassant != NO_ENPASSANT) {
attackedSquares = position->blackPieces | mask[position->enpassant];
} else {
attackedSquares = position->blackPieces;
}
pieceMap = position->whitePawns;
pieceMap &= 0x7F7F7F7F7F7F7F7F;
attackMap = (pieceMap << 9) & attackedSquares;
while (attackMap) {
dest = LSB(attackMap);
orig = dest - 9;
attackMap ^= mask[dest];
m.orig = orig;
m.dest = dest;
if (ROW(dest) == 7) {
m.promotion = QUEEN;
pushMove(m, stack);
m.promotion = KNIGHT;
pushMove(m, stack);
m.promotion = BISHOP;
pushMove(m, stack);
m.promotion = ROOK;
pushMove(m, stack);
} else {
m.promotion = EMPTY;
pushMove(m, stack);
}
}
if (position->enpassant != NO_ENPASSANT) {
attackedSquares = position->blackPieces | mask[position->enpassant];
} else {
attackedSquares = position->blackPieces;
}
pieceMap = position->whitePawns;
pieceMap &= 0xFEFEFEFEFEFEFEFE;
attackMap = (pieceMap << 7) & attackedSquares;
while (attackMap) {
dest = LSB(attackMap);
orig = dest - 7;
attackMap ^= mask[dest];
m.orig = orig;
m.dest = dest;
if (ROW(dest) == 7) {
m.promotion = QUEEN;
pushMove(m, stack);
m.promotion = KNIGHT;
pushMove(m, stack);
m.promotion = BISHOP;
pushMove(m, stack);
m.promotion = ROOK;
pushMove(m, stack);
} else {
m.promotion = EMPTY;
pushMove(m, stack);
}
}
}
The same trick can also be used to tell if your pawn structure needs help. For instance, here:
[D]5k2/8/6n1/2PP4/8/PP1K4/8/8 w - -
None of the pawns support each other. By doing the same attack trick but checking for your own pawns you will see that they don't support each other, but it is easy to make them diagonal.
-
- Posts: 12541
- Joined: Wed Mar 08, 2006 8:57 pm
- Location: Redmond, WA USA
Re: how to claculate with bitboard in fast way
Let's try the code bit again:
Code: Select all
void generateWhitePawnCaptures(ChessPosition * position, moveStack * stack)
{
int orig,
dest;
move m;
BitBoard attackedSquares;
if (position->enpassant != NO_ENPASSANT) {
attackedSquares = position->blackPieces | mask[position->enpassant];
} else {
attackedSquares = position->blackPieces;
}
pieceMap = position->whitePawns;
pieceMap &= 0x7F7F7F7F7F7F7F7F;
attackMap = (pieceMap << 9) & attackedSquares;
while (attackMap) {
dest = LSB(attackMap);
orig = dest - 9;
attackMap ^= mask[dest];
m.orig = orig;
m.dest = dest;
if (ROW(dest) == 7) {
m.promotion = QUEEN;
pushMove(m, stack);
m.promotion = KNIGHT;
pushMove(m, stack);
m.promotion = BISHOP;
pushMove(m, stack);
m.promotion = ROOK;
pushMove(m, stack);
} else {
m.promotion = EMPTY;
pushMove(m, stack);
}
}
if (position->enpassant != NO_ENPASSANT) {
attackedSquares = position->blackPieces | mask[position->enpassant];
} else {
attackedSquares = position->blackPieces;
}
pieceMap = position->whitePawns;
pieceMap &= 0xFEFEFEFEFEFEFEFE;
attackMap = (pieceMap << 7) & attackedSquares;
while (attackMap) {
dest = LSB(attackMap);
orig = dest - 7;
attackMap ^= mask[dest];
m.orig = orig;
m.dest = dest;
if (ROW(dest) == 7) {
m.promotion = QUEEN;
pushMove(m, stack);
m.promotion = KNIGHT;
pushMove(m, stack);
m.promotion = BISHOP;
pushMove(m, stack);
m.promotion = ROOK;
pushMove(m, stack);
} else {
m.promotion = EMPTY;
pushMove(m, stack);
}
}
}
-
- Posts: 10298
- Joined: Thu Mar 09, 2006 12:37 am
- Location: Tel-Aviv Israel
Re: how to claculate with bitboard in fast way
I was talking about evaluation and about counting the number of pawns in the same file.Dann Corbit wrote:Let's try the code bit again:Code: Select all
void generateWhitePawnCaptures(ChessPosition * position, moveStack * stack) { int orig, dest; move m; BitBoard attackedSquares; if (position->enpassant != NO_ENPASSANT) { attackedSquares = position->blackPieces | mask[position->enpassant]; } else { attackedSquares = position->blackPieces; } pieceMap = position->whitePawns; pieceMap &= 0x7F7F7F7F7F7F7F7F; attackMap = (pieceMap << 9) & attackedSquares; while (attackMap) { dest = LSB(attackMap); orig = dest - 9; attackMap ^= mask[dest]; m.orig = orig; m.dest = dest; if (ROW(dest) == 7) { m.promotion = QUEEN; pushMove(m, stack); m.promotion = KNIGHT; pushMove(m, stack); m.promotion = BISHOP; pushMove(m, stack); m.promotion = ROOK; pushMove(m, stack); } else { m.promotion = EMPTY; pushMove(m, stack); } } if (position->enpassant != NO_ENPASSANT) { attackedSquares = position->blackPieces | mask[position->enpassant]; } else { attackedSquares = position->blackPieces; } pieceMap = position->whitePawns; pieceMap &= 0xFEFEFEFEFEFEFEFE; attackMap = (pieceMap << 7) & attackedSquares; while (attackMap) { dest = LSB(attackMap); orig = dest - 7; attackMap ^= mask[dest]; m.orig = orig; m.dest = dest; if (ROW(dest) == 7) { m.promotion = QUEEN; pushMove(m, stack); m.promotion = KNIGHT; pushMove(m, stack); m.promotion = BISHOP; pushMove(m, stack); m.promotion = ROOK; pushMove(m, stack); } else { m.promotion = EMPTY; pushMove(m, stack); } } }
I was not talking about generating pawn captures.
I do not have a bitboard program.
I use bitboards for pawn structure but not for the black pieces so I cannot use your code unless I add more bitboards.
I can probably generate captures faster in my non bitboard program by having a list of captures that is updated incrementally after every move(it can also improve the speed of my perft function) but I need some work to make it without bugs and I think now only about the pawn structure.
Uri
-
- Posts: 12541
- Joined: Wed Mar 08, 2006 8:57 pm
- Location: Redmond, WA USA
Re: how to claculate with bitboard in fast way
What I meant was that you can use the same techniques just with the pawn bitboards to see if the pawns support each other or not.
If you notice the bitboards, masks and shifts, they check for all diagonal captures at once for all the pawns on the board. This same idea can tell you if your pawns support one another.
If you notice the bitboards, masks and shifts, they check for all diagonal captures at once for all the pawns on the board. This same idea can tell you if your pawns support one another.
-
- Posts: 2250
- Joined: Wed Mar 08, 2006 8:47 pm
- Location: Hattingen, Germany
Re: how to claculate with bitboard in fast way
Hi Uri,
it is a good idea to do a minimal update on a pawn bitboard, if you need to calculate other pawn-related stuff rarely, due to the pawn-hash table.
Pawn-bitboards are nice to calculate a lot of setwise pawn-patterns on the fly - based on the front- and back-spans of all white and black pawns, as well their left and rigth attack-sets and the attack spans. That way you get open pawns, passers, outside passers, isolanis, backward, duos, open- and halfopen files, and whatever else. For instance pawns may intersect own front-span and/or own back-span and are then doubled or even tripled. With following white pawn bitboard, c3 intersects the own back-span while c4 intersects the own front-spawn:
With my a1=0,h1=7,h8=63-mapping getting the spans is done by wrapless up- and down fills (shift left/right by 8,16,32), while your mapping is a bit more complicated for that purpose. Otoh your mapping has advantages in getting attack sets...
Gerd
it is a good idea to do a minimal update on a pawn bitboard, if you need to calculate other pawn-related stuff rarely, due to the pawn-hash table.
Pawn-bitboards are nice to calculate a lot of setwise pawn-patterns on the fly - based on the front- and back-spans of all white and black pawns, as well their left and rigth attack-sets and the attack spans. That way you get open pawns, passers, outside passers, isolanis, backward, duos, open- and halfopen files, and whatever else. For instance pawns may intersect own front-span and/or own back-span and are then doubled or even tripled. With following white pawn bitboard, c3 intersects the own back-span while c4 intersects the own front-spawn:
Code: Select all
white pawns front-span back-span
0 0 0 0 0 0 0 0 1 1 1 0 0 1 1 1 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 1 1 1 0 0 1 1 1 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 1 1 1 0 0 1 1 1 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 1 1 1 0 0 1 1 1 0 0 0 0 0 0 0 0
0 0 1 0 0 0 0 0 1 1 1 0 0 1 1 1 0 0 0 0 0 0 0 0
0 0 1 0 0 0 1 0 1 1 0 0 0 1 0 1 0 0 1 0 0 0 0 0
1 1 0 0 0 1 0 1 0 0 0 0 0 0 0 0 0 0 1 0 0 0 1 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 0 0 1 1 1
a1 h1 a1 h1 a1 h1
Gerd