/// <summary>
        ///     Initializes a new instance of the <see cref="EnginePlayerMoveSearcher"/> class
        ///     using the specified parameters.
        /// </summary>
        internal EnginePlayerMoveSearcher(
            [NotNull] ILogger logger,
            [NotNull] GameBoard rootBoard,
            int plyDepth,
            [NotNull] BoardHelper boardHelper,
            [CanBeNull] TranspositionTable transpositionTable,
            [CanBeNull] VariationLineCache previousIterationVariationLineCache,
            [NotNull] GameControlInfo gameControlInfo,
            bool useMultipleProcessors,
            [NotNull] MoveHistoryStatistics moveHistoryStatistics)
        {
            if (plyDepth < CommonEngineConstants.MaxPlyDepthLowerLimit)
            {
                throw new ArgumentOutOfRangeException(
                          nameof(plyDepth),
                          plyDepth,
                          $@"The value must be at least {CommonEngineConstants.MaxPlyDepthLowerLimit}.");
            }

            _logger             = logger ?? throw new ArgumentNullException(nameof(logger));
            _rootBoard          = rootBoard ?? throw new ArgumentNullException(nameof(rootBoard));
            _plyDepth           = plyDepth;
            _boardHelper        = boardHelper;
            _transpositionTable = transpositionTable;
            _previousIterationVariationLineCache = previousIterationVariationLineCache;
            _gameControlInfo       = gameControlInfo ?? throw new ArgumentNullException(nameof(gameControlInfo));
            _useMultipleProcessors = useMultipleProcessors;
            _moveHistoryStatistics = moveHistoryStatistics ?? throw new ArgumentNullException(nameof(moveHistoryStatistics));
            _evaluator             = new Evaluator(gameControlInfo, boardHelper);

            VariationLineCache = new VariationLineCache(rootBoard);
        }
        public EnginePlayer(
            [NotNull] ILogger logger,
            [NotNull] IOpeningBookProvider openingBookProvider,
            GameSide side,
            [NotNull] EnginePlayerParameters parameters)
            : base(side)
        {
            if (openingBookProvider is null)
            {
                throw new ArgumentNullException(nameof(openingBookProvider));
            }

            if (parameters is null)
            {
                throw new ArgumentNullException(nameof(parameters));
            }

            if (parameters.MaxPlyDepth < CommonEngineConstants.MaxPlyDepthLowerLimit)
            {
                throw new ArgumentOutOfRangeException(
                          nameof(parameters.MaxPlyDepth),
                          parameters.MaxPlyDepth,
                          $@"The value must be at least {CommonEngineConstants.MaxPlyDepthLowerLimit}.");
            }

            if (parameters.MaxTimePerMove.HasValue && parameters.MaxTimePerMove.Value <= TimeSpan.Zero)
            {
                throw new ArgumentOutOfRangeException(
                          nameof(parameters.MaxTimePerMove),
                          parameters.MaxTimePerMove,
                          @"The time per move, if specified, must be positive.");
            }

            _logger = logger ?? throw new ArgumentNullException(nameof(logger));

            _openingBookRandom     = new Random();
            MaxPlyDepth            = parameters.MaxPlyDepth;
            _openingBook           = parameters.UseOpeningBook ? openingBookProvider.VariedOpeningBook : null;
            _maxTimePerMove        = parameters.MaxTimePerMove;
            _useMultipleProcessors = parameters.UseMultipleProcessors;

            _transpositionTable = parameters.UseTranspositionTable
                ? new TranspositionTable(_logger, parameters.TranspositionTableSizeInMegaBytes)
                : null;
        }