chess_header - Copy

Bitboard: Moving Pawns

We’ve seen in the previous part how to actually move some pawns. This is fine for the opening position because we know that all the white pawns can move one or two spaces forwards – there are definitely no pieces in the way preventing this. How can we apply this later in the game though where the pawns are not all on one rank and might be blocked by other pieces?

The answer lies with more bitboards. A pawn bitboard is all very well on it’s own for generating candidate moves for the pawns but in order to validate the moves we need some more information.

Consider a white pawn sitting on C2, blocked in by white’s own knight. We’ll ignore all the other pieces for now and assume the board is empty except for these two pieces.

What does the white pawn bitboard contain?

Notice the single, solitary bit set on the second rank. There is no sign of the knight in this representation. So, if we want to generate the moves for the pawn we can start by shifting the board left by 8 to advance the pawn:

Perfect. Our pawn has moved forward a rank. But there’s a problem isn’t there? We’ve just moved the pawn onto the cell containing the knight. The bitboard has no idea the knight is there. We’ve generated a move for the pawn but not a valid move.

So how do we validate the move? We could iterate through the moved pawns bitboard and for every moved pawn we could see if a piece exists on the cell:

This isn’t bad but again requires us to spend CPU cycles iterating through the bits of the bitboard. There is a more efficient way of doing that which we will see later but, like the last time we removed the need for an iteration we can solve this with another bitboard. But what bitboard? What we need is something that can efficiently tell us where every piece on the chess board is.

Like the pawns bitboards we need to update this new bitboard every time a piece is moved. We set a bit in the bitboard if any piece resides in the relevant cell and clear it when a piece moves out of the cell. So, going back to our knight and our pawn in their original positions, the ‘all’ bitboard will contain the following:

Using a bit of bitwise magic we can move the pawn as before but then validate the move by checking it against the ‘all’ board.

How does this work? Let’s take a look at the bits.

If you perform a bitwise ‘and’ of white pawns << 8 and ~board.all you get this:

and

result

Everything is zero in the resulting bitboard indicating there are no valid moves. That’s the result we wanted.

We can take this a stage further and look at pawn double-moves too. Consider this board:

We have the same pawn/knight as before but in addition we have a pawn on the E file that can make a valid double move and a pawn on the G file that can move once but not twice. The white pawns bitboard looks like this:

The ‘all’ bitboard looks like this:

If we now calculate the shifted pawn bitboard for a single move then and it with ~board.all like before we get this:

Note there are only two pawns left thanks to the knight we looked at before. There are two valid single pawn moves. Now let’s try to move forward again by shifting by another 8 bits.

Now and this with ~board.all again and you get:

Just one pawn left – one pawn which can make a valid double move.

Let’s put this into code. We will start writing a function that calculates all the valid moves for a given position and start implementing it with the pawn moves we’ve just looked at. The function will not be complete yet as we need to do something with the bitboards of valid moves that we generated however it is a start.

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code class="" title="" data-url=""> <del datetime=""> <em> <i> <q cite=""> <strike> <strong> <pre class="" title="" data-url=""> <span class="" title="" data-url="">