public void CalculateSubtreeMetricsForOpponent(MetricsEvaluator evaluator, BiconnectedComponent entryComponent)
        {
            EntryComponentForOpponent = entryComponent;
            BiconnectedComponent bestComponent = null;
            double valueOfBestComponent        = double.NegativeInfinity;
            int    branchCount = 0;

            // TODO: Order the components from most promising to least promising, in case there is a cycle:
            foreach (BiconnectedComponent component in biconnectedComponents)
            {
                if (component != entryComponent) // TODO: && component.OccupationStatus != OccupationStatus.You)
                {
                    if (component.IsSubTreeVisitedForOpponent)
                    {
                        System.Diagnostics.Debug.WriteLine("Component {0} not being visited, as it has been visited previously for Opponent");
                    }
                    else
                    {
                        component.CalculateSubtreeMetricsForOpponent(evaluator, this);
                        Metrics componentSubtreeMetrics = component.SubtreeMetricsForOpponent;

                        double valueOfComponent = evaluator.Evaluate(componentSubtreeMetrics);
                        if (valueOfComponent >= valueOfBestComponent)
                        {
                            valueOfBestComponent = valueOfComponent;
                            bestComponent        = component;
                        }
                        branchCount += componentSubtreeMetrics.NumberOfComponentBranchesInTree;
                    }
                }
            }

            // If this is a leaf cut vertex, then its branchCount is 1:
            if (branchCount == 0)
            {
                branchCount = 1;
            }

            ExitComponentForOpponent = bestComponent;
            Metrics opponentsMetricsForCutVertexOnly = CalculateOpponentsMetricsForCellStateOnly();

            if (bestComponent == null)
            {
                subtreeMetricsForOpponent = opponentsMetricsForCutVertexOnly;
            }
            else
            {
                subtreeMetricsForOpponent = opponentsMetricsForCutVertexOnly + bestComponent.SubtreeMetricsForOpponent;
            }

            subtreeMetricsForOpponent.NumberOfComponentBranchesInTree = branchCount;
            IsSubTreeVisitedForOpponent = true;
        }
        // TODO: Add CompartmentStatus property and a method to calculate it

        public void CalculateSubtreeMetricsForPlayer(PlayerType playerType, MetricsEvaluator evaluator, CellState entryVertex)
        {
            switch (playerType)
            {
            case PlayerType.You:
                CalculateSubtreeMetricsForYou(evaluator, entryVertex);
                break;

            case PlayerType.Opponent:
                CalculateSubtreeMetricsForOpponent(evaluator, entryVertex);
                break;
            }
        }
        public void CalculateSubtreeMetricsForOpponent(MetricsEvaluator evaluator, CellState entryVertex)
        {
            EntryVertexForOpponent = entryVertex;
            CellState bestCutVertex        = null;
            double    valueOfBestCutVertex = double.NegativeInfinity;
            int       branchCount          = 0;

            // TODO: Order the cut vertices from most promising to least promising, in case there is a cycle:
            foreach (CellState cutVertex in cutVertices)
            {
                if (cutVertex != entryVertex && cutVertex.OccupationStatus != OccupationStatus.You)
                {
                    if (cutVertex.IsSubTreeVisitedForOpponent)
                    {
                        System.Diagnostics.Debug.WriteLine("Cut vertex {0} not being visited, as it has been visited previously for Opponent");
                    }
                    else
                    {
                        cutVertex.CalculateSubtreeMetricsForOpponent(evaluator, this);
                        Metrics cutVertexSubtreeMetrics = cutVertex.SubtreeMetricsForOpponent;
                        double  valueOfCutVertex        = evaluator.Evaluate(cutVertexSubtreeMetrics);
                        if (valueOfCutVertex >= valueOfBestCutVertex)
                        {
                            valueOfBestCutVertex = valueOfCutVertex;
                            bestCutVertex        = cutVertex;
                        }
                        branchCount += cutVertexSubtreeMetrics.NumberOfComponentBranchesInTree;
                    }
                }
            }

            // If this is a leaf component, then its branchCount is 1:
            if (branchCount == 0)
            {
                branchCount = 1;
            }

            ExitVertexForOpponent = bestCutVertex;
            if (bestCutVertex == null)
            {
                subtreeMetricsForOpponent = opponentsMetricsForComponentOnly.Clone();
            }
            else
            {
                subtreeMetricsForOpponent = opponentsMetricsForComponentOnly + bestCutVertex.SubtreeMetricsForOpponent;
            }

            subtreeMetricsForOpponent.NumberOfComponentBranchesInTree = branchCount;
            IsSubTreeVisitedForOpponent = true;
        }