This is my first post on these forums. I recently started working on my first engine in C++, which can currently only hold and print out the board state, nothing else. I am slowly adding one thing at a time, being careful to really think each step through. I decided to go with bitboards, since I have experience working with 6502 assembly (which is entirely different, but requires a LOT of bit wrangling and unconventional "tricks"). I am keeping some redundant mailboxes as well, since it doesn't add much overhead and might save time making certain calculations, and I can easily remove them if I want.mvanthoor wrote: ↑Wed Feb 24, 2021 7:22 pm...Mike Sherwin wrote: ↑Wed Feb 24, 2021 6:54 pm In some of your code snippets I've looked at I remember seeing lots of "if" statements. In my code there are very few if statements. For example in my make and unmake move routines there is not a single "if" statement and only one switch statement each. In all my pawn move generation and make/unmake there is not a single "if" statement.
...
If statements are the bane of high performance. Mispredictions are expensive. The more "if" statements there are the easier it is to overflow the branch prediction tables. And the constantly changing state of a chess engine makes for a high prediction fail rate.
With regard to if-statements... if you think my code has a lot of then, you should look at some other engines. My engine uses if and switch statements sparingly, compared to what I normally see.
There is something like branchless programming. One day I'll have to look into this to see if there are places in my engine where I can use that.
I have a get_mail() function which updates the mailboxes (white/black) to line up with the bitboards, and my first rough implementation used a simple algorithm with many IF statements:
Code: Select all
void position::get_mail ()
{
uint64_t mask = force64(1);
for (int i = 0; i < 64; ++i, mask = mask << 1)
{
// check for case of no piece at mask position
if (((white | black) & mask) == 0)
{
whitemail[i] = blackmail[i] = EMPTY;
continue;
}
// mail = pointer to blackmail or whitemail, depending on piece color
PIECE* mail = whitemail;
if (black & mask) mail = blackmail;
if (king & mask) *(mail + i) = KING;
else if (queen & mask) *(mail + i) = QUEEN;
else if (rook & mask) *(mail + i) = ROOK;
else if (bishop & mask) *(mail + i) = BISHOP;
else if (knight & mask) *(mail + i) = KNIGHT;
else *(mail + i) = PAWN;
}
return;
}
Code: Select all
void position::get_mail ()
{
// first clear both mailboxes, setting to EMPTY
for (int i = 0; i < 64; ++i) whitemail[i] = blackmail[i] = EMPTY;
// then loop through and set each type of piece + color seperately
bitboard piecemask;
piecemask.bb = white & pawn.bb;
while (piecemask.bb) whitemail[piecemask.bitpullr()] = PAWN;
piecemask.bb = black & pawn.bb;
while (piecemask.bb) blackmail[piecemask.bitpullr()] = PAWN;
piecemask.bb = white & knight.bb;
while (piecemask.bb) whitemail[piecemask.bitpullr()] = KNIGHT;
piecemask.bb = black & knight.bb;
while (piecemask.bb) blackmail[piecemask.bitpullr()] = KNIGHT;
piecemask.bb = white & bishop.bb;
while (piecemask.bb) whitemail[piecemask.bitpullr()] = BISHOP;
piecemask.bb = black & bishop.bb;
while (piecemask.bb) blackmail[piecemask.bitpullr()] = BISHOP;
piecemask.bb = white & rook.bb;
while (piecemask.bb) whitemail[piecemask.bitpullr()] = ROOK;
piecemask.bb = black & rook.bb;
while (piecemask.bb) blackmail[piecemask.bitpullr()] = ROOK;
piecemask.bb = white & queen.bb;
while (piecemask.bb) whitemail[piecemask.bitpullr()] = QUEEN;
piecemask.bb = black & queen.bb;
while (piecemask.bb) blackmail[piecemask.bitpullr()] = QUEEN;
piecemask.bb = white & king.bb;
while (piecemask.bb) whitemail[piecemask.bitpullr()] = KING;
piecemask.bb = black & king.bb;
while (piecemask.bb) blackmail[piecemask.bitpullr()] = KING;
return;
}