2

If I have a bitboard (e.g. for knight squares he can move to) like this:

00000000
00000000
00000000
00000000
00000000
01000000
00100000
N0000000

How can I "convert" it into a move or "apply" that move?

1 Answer 1

2

There are actually two questions in your post

  • How to convert Attacks in Bitboards to a list of moves?

  • How to represent those moves?


  • How to represent those moves?

This question has been discussed here and here thoroughly. But to provide some context to the readers of this post, a very simple way to do this can be to use a class / struct to represent a move

  • From ( where the moving piece was )
  • To ( where the moving piece will be )
  • Special Move Flag ( whether the move was a special move, i.e enpassant, casting, promotion)
  • Promoted Piece ( if the move was a promotion move, what piece did it promote to )

You can also have extra attributes such as captured piece, type of castle etc. But that information can also be deduced using the From and To squares.

So considering the above, we can represent the move as follows

struct Move {
    char from; 
    char to;   
    char spMoveFlag;
    char promotedPiece;
};

However, a lot of chess engines, including mine use another method that can compress the move into just 16 bits. Read more about that here.

Once we know what a move is, we can answer the next question


  • How to convert Attacks in Bitboards to a list of moves?

Let's consider that we have a knight on the square d4. We also have a function that returns the attacks of a knight given the square.

. . . . . . . . 
. . . . . . . . 
. . 1 . 1 . . . 
. 1 . . . 1 . . 
. . . n . . . .   =  knightattacks(SQ_D4)
. 1 . . . 1 . . 
. . 1 . 1 . . . 
. . . . . . . . 

So let's store this inside a variable knightAttacks

uint64_t knightAttacks = getKnightAttacksBB(SQ_D4);

If you notice carefully we already have 1 of the 4 attributes we need to represent the move, which is the From square - D4. Now all we need to do is somehow get the To square to complete this since a knight cannot perform any kind of special moves.

A very common method is to pop the least significant bit until your knightAttacks is left with nothing i.e 0.

0000011100001000 
            ^
            Least significant bit (lsb)

You can follow the link I provided to know how you can perform this, or there is a chance that your compiler might already provide you with it.

You simply need to create a function that clears the lsb of a bitboard and returns its index. Let's call it poplsb().

Altogether, your code can look like this

int from = SQ_D4;
uint16_t knightAttacks = getknightAttacks(from);

while (knightAttacks)  {
     int to = poplsb(knightAttacks);
     MyMoveList.Add( NewMove(from, to, 0, 0) ); // The last two 0's denote that there is no special move
}

This works because each time you pop the lsb, a bit gets cleared until the number is == 0. That's when the loop stops and you have a perfectly good list of moves. The same idea applies to any kind of moves you have created using Bitboards.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.