This is a set of 3 changes:
1. Simplify the structure of the solver class:
- make firstMoves and winMoves private members and add getter for them
- replace mutex protected bool with atomic bool
- do not directly expose m_shouldEnd, but provide a stopExecution
function
- use in-class initialization of member variables
- remove debug variable, and the DEBUG_HINTS define which controlled it,
use #ifndef NDEBUG to print the debug messages for now
- Solver: use a unique_ptr for the MemoryManager
2. Introduce a smaller SolverInterface, hiding the complexity of Solver
This change:
- extract all the publically used Solver functionality into
SolverInterface, which consists only of virtual functions
- move solverinterface into its own header, to minimize includes
- converts users which used Solver directly to SolverInterface
3. Convert Solver into a template, templated over the number of piles
The number of piles is known in each Solver subclass at compile time,
thus a subclass with n piles does now inherit from Solver<n>.
m_number_piles and its setter become redundant with this change, and are
removed
This enable the conversion of member variables which were
dynamically allocated arrays into std::arrays, increasing type safety
and causing an abort/exception on out-of-boundary access. Furthermore,
the compiler can now better reason about some of the loops (though this
doesn't really matter performance wise)