public TMetric Search(TNode node, int depth, TMetric alfa, TMetric beta, TState state, CancellationToken ct)
        {
            ct.ThrowIfCancellationRequested();

            if (node.Children == null && depth > 0)
            {
                _brancher.Branch(node, state);
            }

            if (depth == 0 || node.Children.Length == 0)
            {
                var result = _evaluator.Evaluate(state);
                node.Result = result;
                return(result);
            }

            if (node.IsMaxPlayer)
            {
                var maxVal = _minValue;
                foreach (var child in node.Children)
                {
                    var childState = _stateTransitions.GoDown(state, child);
                    var result     = Search(child, depth - 1, alfa, beta, childState, ct);
                    state = _stateTransitions.GoUp(childState, child);

                    if (!_comparator.IsBigger(maxVal, result))
                    {
                        maxVal         = result;
                        node.BestChild = child;
                    }

                    if (!_comparator.IsBigger(beta, result))
                    {
                        break;
                    }

                    alfa = _comparator.IsBigger(result, alfa) ? result : alfa;
                }

                // todo - refactor - remove extra variables
                node.Result = maxVal;
                return(maxVal);
            }

            var minVal = _maxValue;

            foreach (var child in node.Children)
            {
                var childState = _stateTransitions.GoDown(state, child);

                var result = Search(child, depth - 1, alfa, beta, childState, ct);
                state = _stateTransitions.GoUp(childState, child);

                if (!_comparator.IsBigger(result, minVal))
                {
                    minVal         = result;
                    node.BestChild = child;
                }

                if (!_comparator.IsBigger(result, alfa))
                {
                    break;
                }

                beta = _comparator.IsBigger(beta, result) ? result : beta;
            }

            // todo - refactor - remove extra variables
            node.Result = minVal;
            return(minVal);
        }