Remove mutable from Minimax_AI search cache
Closed this issue · 1 comments
As it is now, it is impossible for the same player to play different games in different threads since the search cache will be stomped on by multiple threads, leading to principle variations with illegal moves for the wrong board.
Remove the mutable keyword, fix up the const-correctness, and pass the Players by value. Can't work due to inheritance and would cause slicing.
First(-ish) idea: store seach cache data in a Can't work because all standard chess boards with the default starting state have the same hash.std::unordered_map
with the pre-move board hash as the key.
Make the Can't work. In the call to play_game*()
functions templates on the player type.play_game*()
from start_game()
, the type of the white
and black
is std::unique_ptr<Player>
and the type of the parameter for the play_game*()
functions are const Player&
. The compiler has no way of knowing what the dynamic type of the Player*
instances are.
Latest idea: delete mutable
keyword and replace const Player&
with Player&
in all game parameters. This basically gives up on this issue. The non-const
reference parameter can serve as a warning that the classes are modified in a non-thread-safe manner.
How to run a round-robin tournament with thread-unsafe players:
This tournament style has every player play every other player twice with each player playing both white and black.
std::vector<Minimax_AI> pool;
for(size_t gap = 1; gap < pool.size(); ++gap)
{
for(size_t white_index = 0; white_index < pool.size(); ++white_index)
{
black_index = (white_index + gap) % pool.size();
// play game with pool[white_index] and pool[black_index]
// Use Thread_Limiter or std::counting_semaphore where
// the maximum number of games is
// std::min(maximum_simultaneous_games, pool.size())
}
}
This algorithm makes it impossible for the same Minimax_AI
instance to play more than one game at the same time, which was the primary problem this issue was trying to address.
The ultimate solution was to create a function in Gene_Pool.cpp that took the Minimax_AI
by value and then called play_game()
on the copied argument.
You don't need a comprehensive solution when the problem only occurs in one place.