Board struct
We are starting with one of the chess engine’s basic components. There are several reasons for implementing the board struct first:
- It is a very concrete and relatable structure.
- The implementation is straightforward.
- Many other parts of the engine need a board to function.
In the design overview on the previous page we know that we need different data structures to represent the board and its state while playing the game. The Board struct serves as the container. The board consists of the following components:
- Bitboards
- 6 per side; one for each piece
- 1 per side for all pieces of that side
- Game State
- Game History
- Piece List
- Zobrist Randoms
In Rustic, the Board struct is implemented like this:
pub struct Board {
pub bb_pieces: EverySide<EveryPiece<Bitboard>>,
pub bb_side: EverySide<Bitboard>,
pub game_state: GameState,
pub history: History,
pub piece_list: EverySquare<Piece>,
zobrist_randoms: Arc<ZobristRandoms>,
}
By instantiating the Board struct, we can create a new board for the engine to
work with. We implement a Board::new() function to facilitate this:
impl Board {
pub fn new() -> Self {
Self {
bb_pieces: EverySide::new(EveryPiece::new(Bitboard::empty())),
bb_side: EverySide::new(Bitboard::empty()),
game_state: GameState::new(),
history: History::new(),
piece_list: EverySquare::new(Piece::None),
zobrist_randoms: Arc::new(ZobristRandoms::new()),
}
}
}
This is how it is used:
let board = Board::new();
Now we have a new empty board. Normally, the engine will create and initialize
its primary board in the main engine struct which is then used for game play.
However, there are some functions that create their own, so as not to mess up
the engine’s main board. One of thse functions is perft, which we will discuss
at a later time.
Now that we know how we can create an empty board, we can start adding functionality to it. We need pieces to play with, so we’re going to look into the bitboards first in the next chapter.
Well… after you made sure you thoroughly understand the binary system and bitwise operations. Last chance to study these topics before you’re going to need them. A lot. Don’t say I didn’t warn you. I did: in the second prerequisite. It would also be a good idea to read about defining base types using enums and newtypes if you haven’t already. It is best to start with that at the very beginning, because adding them later is a lot of work. Ask me how I know.
Okay; now that you’re back, let’s take a look at bitboards.