Bitboards (aka bitmaps)

Introduction and some History
Manipulating Bitboards
Move Generation using Bitboards
How Djinn Utilizes Bitboards


Introduction and some History

Bitboards are all the rage these days thanks to Robert Hyatt and his open-source program Crafty.  Aspiring chess programmers are bombarded with the term, but it's rarely explained.  Discussions on rotated bitboards only exacerbate the situation, since they are even less understood than plain vanilla bitboards.  Before we delve too deeply into the technical aspects of bitboards (or bitmaps as they are often called) we should review a bit of their history.  It's widely accepted that Kaissa, a Russian chess program circa. 1977, was the first bitboard-based  program.  David Slate and Lawrence Atkin, of Chess 4.5 fame, discovered the idea independently while at Northwestern University.

Fundamentally, bitboards are nothing more than a different way to represent the chess board (i.e. an alternative data representation).  What makes them intriguing, is the unique way they take advantage of the modern computer's architecture.  Without getting too technical, all computers are based on the binary or base 2 numbering system.  For comparison, the mathematics we use in our everyday lives, is a decimal system or base 10 (not coincidentally, derived from the fact that we have 10 fingers to count on). 

Unlike a decimal number, which can assume 10 distinct values, a binary number can assume only one of two states, either 1 or 0.  Like a light switch, it is either on or off.  These individual binary switches are referred to as "bits".  For convenience, bits are grouped into bytes and words of length 8 and 32 respectively.   It is possible for the length of a byte or word to vary, but most architectures stick with a length of 8 and 32.

Computers support boolean operations and logic.  Boolean logic is named after its inventor, George Boole who was born Nov. 2, 1815 in Lincolnshire, England (long before the first digital computer was a gleam in anyone's eye)!  If you'll bear with me a bit I'll explain why we care about George Boole and his slightly odd logic.  Boolean logic supports a number of fundamental operations which operate very nicely on the binary bits of a computer.  The most important operations are logical AND, OR and XOR.  Rather than using words to describe their operation, mathematicians and engineers use a diagram known as a truth table, shown below (note, A and B are the two input bits that we are performing the boolean operation on).

A
B
AND
OR
XOR
0
0
0
0
0
0
1
0
1
1
1
0
0
1
1
1
1
1
1
0

What this is telling us is that if we apply the logical AND operation to two bits the result is 0 unless both bits are 1.  Conversely, if we apply the logical OR operation to two bits the result is 1 if either bit is set to 1.  Finally, the XOR operation tells us that one, but not both bits must be set to a 1 if we want a 1.  The XOR operator has the interesting and useful property that if it is applied twice we get back the original number.  We'll take advantage of this property later when we examine the operation of the program's hash table.  The last boolean operation that we need is the NOT operator (represented by the '~' tilde symbol).  A logical NOT, or complement, of a byte or word inverts the individual bits of the value.  For example, 10010111 complemented would be 01101000.

Bitboards take advantage of the serendipitous fact  that a chess board is composed of 64 squares, which is a multiple of eight.  Utilizing this bit of luck, it is possible to represent the state of the chess board using a set of bitboards.  For example, a bitboard representing the location of all the pieces on their original squares would look like this internally.

11111111 11111111 00000000 00000000 00000000 00000000 11111111 1111111

Granted this is a bit obtuse, but the computer has no problem understanding it.  Reformatting the bitboard makes clear the relationship between the pieces and the individual bits.

Initial starting position
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
       
Another example of information that could be stored is "...all the squares attacked by a white knight on D4".

Knight attack from D4
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
1
0
1
0
0
0
0
1
0
0
0
1
0
0
0
0
0
0
0
0
0
0
0
1
0
0
0
1
0
0
0
0
1
0
1
0
0
0
0
0
0
0
0
0
0
0
   
In truth, the type of information that can be represented is only limited by the programmer's imagination.   As you become more comfortable with bitboards, novel and interesting ways of using them will become readily apparent. 

For example, Djinn regularly extracts the following types of information:
Modern computers perform boolean logic exceedingly fast.  The latest microprocessors from Intel and AMD can perform millions of boolean operations per second!  We can use these operators to quickly extract information about the board and pieces.  An example, if we have the following two bitboards,


Bishop attack from D5
1
0
0
0
0
0
1
0
0
1
0
0
0
1
0 0
0
0
1
0
1
0
0
0
0
0
0
0
0
0
0
0
0
0
1
0
1
0
0
0
0
1
0
0
0
1
0
0
1
0
0
0
0
0
1
0
0
0
0
0
0
0
0
1


Black pawns initial position
0
0
0
0
0
0
0
0
1 1 1 1 1 1 1 1
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0

we can quickly extract the black pawns subject to capture by the white bishop by applying the AND operator.  ANDing the two bitboards produces a bitboard of all the black pawns under attack by the bishop.  We can use this information to generate the pawns subject to capture by the bishop.

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
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
   
Of course, the obvious and valid question is "... so what, how do I extract this information?"  That's the subject of the next section.

<<

[ home ] [ back to top ]