lojic wrote: ↑Thu Feb 04, 2021 2:41 am
I think maybe what you call "history array" I called "move list" i.e. the list of moves previously made by both sides.
Well... in most chess engines, MoveList or move_list is the one that contains the moves that have just been generated by the move generator. What I have noticed is that there is a sort of a "language" that has developed, because of all the interchange of information.
mvanthoor wrote: ↑Wed Feb 03, 2021 10:05 pm
Just out of curiosity, why did you choose to copy the game state vs. doing an incremental make/unmake? It seems like the latter would be faster, and by using Rust, you have the chance to have a *really* speedy engine. Or maybe I'm misunderstanding your implementation.
This is my Board struct:
Code: Select all
pub struct Board {
pub bb_pieces: [[Bitboard; NrOf::PIECE_TYPES]; Sides::BOTH],
pub bb_side: [Bitboard; Sides::BOTH],
pub game_state: GameState,
pub history: History,
pub piece_list: [Piece; NrOf::SQUARES],
zr: Arc<ZobristRandoms>,
}
As you can see, I packed all the information except for the arrays holding the piece bitboards into the GameState struct. ("zr" is a reference to the ZobristRandoms struct that creates the Zobrist keys.)
There are two options:
1.
When making a move, I incrementally update all the values in the game state.
When making a move, I could of course incrementally reverse all the values in the game state.
However, moving the pieces does not cause thing such as the ep-square being set, or half-move clock to be reset, etc... it's make that does this. Therefore I would have to recalculate what those values would have been, or I would have to copy them back and forth.
2.
I could also just get the game state, add the move that is going to be made to it, and push it into the history list. When reversing, I pop the game state off the list (directly into the board), and then reverse the move using a helper function that ONLY reverses the move and does not touch any of the just restored game state values.
I have tested both, and the second is MUCH faster, at least in my engine. It is also cleaner with regard to code.
(I actually use an intermediate variable "current_game_state" in between, to which I copy the current game state, and then add the move to it before I push it. I could also immediately add the move to the game-state, directly in the board and then copy/push it from the board to the history array. When I do that however, the program becomes 3% slower. It seems that the compiler can optimize better, or the memory layout is better, when there's an intermediate variable.)