how to claculate with bitboard in fast way

Discussion of chess software programming and technical issues.

Moderators: hgm, Rebel, chrisw

Uri Blass
Posts: 10298
Joined: Thu Mar 09, 2006 12:37 am
Location: Tel-Aviv Israel

how to claculate with bitboard in fast way

Post by Uri Blass »

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
Dann Corbit
Posts: 12541
Joined: Wed Mar 08, 2006 8:57 pm
Location: Redmond, WA USA

Re: how to claculate with bitboard in fast way

Post by Dann Corbit »

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.
Dann Corbit
Posts: 12541
Joined: Wed Mar 08, 2006 8:57 pm
Location: Redmond, WA USA

Re: how to claculate with bitboard in fast way

Post by Dann Corbit »

Let's try the code bit again:

Code: Select all

void generateWhitePawnCaptures&#40;ChessPosition * position, moveStack * stack&#41;
&#123;

    int             orig,
                    dest;
    move            m;
    BitBoard        attackedSquares;

    if &#40;position->enpassant != NO_ENPASSANT&#41; &#123;
        attackedSquares = position->blackPieces | mask&#91;position->enpassant&#93;;
    &#125; else &#123;
        attackedSquares = position->blackPieces;
    &#125;

    pieceMap = position->whitePawns;
    pieceMap &= 0x7F7F7F7F7F7F7F7F;
    attackMap = &#40;pieceMap << 9&#41; & attackedSquares;

    while &#40;attackMap&#41; &#123;
        dest = LSB&#40;attackMap&#41;;
        orig = dest - 9;
        attackMap ^= mask&#91;dest&#93;;
        m.orig = orig;
        m.dest = dest;

        if &#40;ROW&#40;dest&#41; == 7&#41; &#123;
            m.promotion = QUEEN;
            pushMove&#40;m, stack&#41;;
            m.promotion = KNIGHT;
            pushMove&#40;m, stack&#41;;
            m.promotion = BISHOP;
            pushMove&#40;m, stack&#41;;
            m.promotion = ROOK;
            pushMove&#40;m, stack&#41;;
        &#125; else &#123;
            m.promotion = EMPTY;
            pushMove&#40;m, stack&#41;;
        &#125;
    &#125;

    if &#40;position->enpassant != NO_ENPASSANT&#41; &#123;
        attackedSquares = position->blackPieces | mask&#91;position->enpassant&#93;;
    &#125; else &#123;
        attackedSquares = position->blackPieces;
    &#125;

    pieceMap = position->whitePawns;
    pieceMap &= 0xFEFEFEFEFEFEFEFE;
    attackMap = &#40;pieceMap << 7&#41; & attackedSquares;

    while &#40;attackMap&#41; &#123;
        dest = LSB&#40;attackMap&#41;;
        orig = dest - 7;
        attackMap ^= mask&#91;dest&#93;;
        m.orig = orig;
        m.dest = dest;

        if &#40;ROW&#40;dest&#41; == 7&#41; &#123;
            m.promotion = QUEEN;
            pushMove&#40;m, stack&#41;;
            m.promotion = KNIGHT;
            pushMove&#40;m, stack&#41;;
            m.promotion = BISHOP;
            pushMove&#40;m, stack&#41;;
            m.promotion = ROOK;
            pushMove&#40;m, stack&#41;;
        &#125; else &#123;
            m.promotion = EMPTY;
            pushMove&#40;m, stack&#41;;
        &#125;
    &#125;
&#125;

Uri Blass
Posts: 10298
Joined: Thu Mar 09, 2006 12:37 am
Location: Tel-Aviv Israel

Re: how to claculate with bitboard in fast way

Post by Uri Blass »

Dann Corbit wrote:Let's try the code bit again:

Code: Select all

void generateWhitePawnCaptures&#40;ChessPosition * position, moveStack * stack&#41;
&#123;

    int             orig,
                    dest;
    move            m;
    BitBoard        attackedSquares;

    if &#40;position->enpassant != NO_ENPASSANT&#41; &#123;
        attackedSquares = position->blackPieces | mask&#91;position->enpassant&#93;;
    &#125; else &#123;
        attackedSquares = position->blackPieces;
    &#125;

    pieceMap = position->whitePawns;
    pieceMap &= 0x7F7F7F7F7F7F7F7F;
    attackMap = &#40;pieceMap << 9&#41; & attackedSquares;

    while &#40;attackMap&#41; &#123;
        dest = LSB&#40;attackMap&#41;;
        orig = dest - 9;
        attackMap ^= mask&#91;dest&#93;;
        m.orig = orig;
        m.dest = dest;

        if &#40;ROW&#40;dest&#41; == 7&#41; &#123;
            m.promotion = QUEEN;
            pushMove&#40;m, stack&#41;;
            m.promotion = KNIGHT;
            pushMove&#40;m, stack&#41;;
            m.promotion = BISHOP;
            pushMove&#40;m, stack&#41;;
            m.promotion = ROOK;
            pushMove&#40;m, stack&#41;;
        &#125; else &#123;
            m.promotion = EMPTY;
            pushMove&#40;m, stack&#41;;
        &#125;
    &#125;

    if &#40;position->enpassant != NO_ENPASSANT&#41; &#123;
        attackedSquares = position->blackPieces | mask&#91;position->enpassant&#93;;
    &#125; else &#123;
        attackedSquares = position->blackPieces;
    &#125;

    pieceMap = position->whitePawns;
    pieceMap &= 0xFEFEFEFEFEFEFEFE;
    attackMap = &#40;pieceMap << 7&#41; & attackedSquares;

    while &#40;attackMap&#41; &#123;
        dest = LSB&#40;attackMap&#41;;
        orig = dest - 7;
        attackMap ^= mask&#91;dest&#93;;
        m.orig = orig;
        m.dest = dest;

        if &#40;ROW&#40;dest&#41; == 7&#41; &#123;
            m.promotion = QUEEN;
            pushMove&#40;m, stack&#41;;
            m.promotion = KNIGHT;
            pushMove&#40;m, stack&#41;;
            m.promotion = BISHOP;
            pushMove&#40;m, stack&#41;;
            m.promotion = ROOK;
            pushMove&#40;m, stack&#41;;
        &#125; else &#123;
            m.promotion = EMPTY;
            pushMove&#40;m, stack&#41;;
        &#125;
    &#125;
&#125;

I was talking about evaluation and about counting the number of pawns in the same file.

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
Dann Corbit
Posts: 12541
Joined: Wed Mar 08, 2006 8:57 pm
Location: Redmond, WA USA

Re: how to claculate with bitboard in fast way

Post by Dann Corbit »

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.
Gerd Isenberg
Posts: 2250
Joined: Wed Mar 08, 2006 8:47 pm
Location: Hattingen, Germany

Re: how to claculate with bitboard in fast way

Post by Gerd Isenberg »

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:

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
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