public HSCardCluster GenerateCardCluster(String seed, ref Dictionary <String, CardObject> cardTable, ref HoningNetwork <String> net)
        {
            String s = seed.ToLower();

            if (!net.HasNode(s))
            {
                return(null);
            }

            HSCardCluster cluster = new HSCardCluster();

            cluster.card = seed;

            List <String> targets   = new List <string>();
            CardObject    Antonidas = cardTable[s];

            net.getMfList(s, out targets, "essential");

            Dictionary <String, String> selfAbilityFilter = GenerateAbilityFilter();

            foreach (CardAbility a in Antonidas.abilities)
            {
                if (selfAbilityFilter.ContainsKey(a.ability.ToLower()))
                {
                    if (!cluster.receiver.ContainsKey(a.ability))
                    {
                        Dictionary <String, HoningNode <String> > comboByTargets = GetCardsBySingleBound(ref net, a.target[0], "terminal");

                        cluster.receiver.Add(a.ability, comboByTargets);
                    }
                }
            }

            Dictionary <String, HoningNode <String> > giverAbilities;

            net.GetRelationsFromEssential(s, out giverAbilities);
            FilterAbilities(ref selfAbilityFilter, ref giverAbilities);
            foreach (String key in giverAbilities.Keys)
            {
                Dictionary <String, HoningNode <String> > comboByTargets = GetCardsBySingleBound(ref net, key, "terminal");

                RemoveUnwantedTargets(ref comboByTargets, ref cardTable, ref targets, key);

                cluster.giver.Add(key, comboByTargets);
            }

            return(cluster);
        }
        public List <String> GreedyExpansion(
            ref HoningNetwork <String> net,
            ref HSCardExpasionConfiguration config,
            ref Dictionary <String, CardObject> cardTable,
            ExpansionGeneralPolitics politic,
            PriorityPolitics giverPriorities,
            PriorityPolitics receiverPriorities,
            String seed)
        {
            HSCardCluster base_cluster = GenerateCardCluster(seed, ref cardTable, ref net);

            if (base_cluster == null)
            {
                return(null);
            }

            if (config.total_mana == 0)
            {
                return(null);
            }

            List <String> comboNodes = new List <String>();

            List <String> combo = new List <String>();

            combo.Add(base_cluster.card);

            Dictionary <String, bool> markers = new Dictionary <string, Boolean>();

            List <String> giver_recruiting;
            List <String> receiver_recruiting;

            if (config.giver_inflation)
            {
                giver_recruiting = RecruitNeighbours(ref net, ref base_cluster.giver, ref config, ref cardTable, ref politic, ref giverPriorities, ref markers, ref combo);
                comboNodes.AddRange(giver_recruiting);
            }

            if (config.receiver_inflation)
            {
                receiver_recruiting = RecruitNeighbours(ref net, ref base_cluster.receiver, ref config, ref cardTable, ref politic, ref receiverPriorities, ref markers, ref combo);
                comboNodes.AddRange(receiver_recruiting);
            }

            while (comboNodes.Count > 0)
            {
                String current = comboNodes.First();
                comboNodes.Remove(current);
                HSCardCluster new_cluster = GenerateCardCluster(current, ref cardTable, ref net);

                if (!markers.ContainsKey(current))
                {
                    markers.Add(current, true);
                }

                combo.Add(new_cluster.card);

                if (config.giver_inflation)
                {
                    giver_recruiting = RecruitNeighbours(ref net, ref new_cluster.giver, ref config, ref cardTable, ref politic, ref giverPriorities, ref markers, ref combo);
                    comboNodes.AddRange(giver_recruiting);
                }

                if (config.receiver_inflation)
                {
                    receiver_recruiting = RecruitNeighbours(ref net, ref new_cluster.receiver, ref config, ref cardTable, ref politic, ref receiverPriorities, ref markers, ref combo);
                    comboNodes.AddRange(receiver_recruiting);
                }
            }

            // Mana threshold 10 mana = 1 turn, 30 mana = 3 turns combo
            if (config.cutByManaCost)
            {
                List <String> new_output = new List <String>();
                int           total_mana = 0;
                foreach (String key in combo)
                {
                    String s = key.ToLower();
                    int    mana_cost;
                    Int32.TryParse(cardTable[s].cost, out mana_cost);
                    total_mana += mana_cost;

                    if (total_mana >= config.total_mana)
                    {
                        break;
                    }

                    new_output.Add(key);

                    if (new_output.Count == config.maxCards)
                    {
                        break;
                    }
                }

                return(new_output);
            }

            return(combo);
        }
        public void GreedyExpansionDelegated(
            ref HoningNetwork <String> net,
            ref HSCardExpasionConfiguration config,
            ref Dictionary <String, CardObject> cardTable,
            ExpansionGeneralPolitics politic,
            PriorityPolitics giverPriorities,
            PriorityPolitics receiverPriorities,
            String seed,
            out List <List <String> > out_subcomboClusters,
            out List <String> out_simpleComboList)
        {
            HSCardCluster base_cluster = GenerateCardCluster(seed, ref cardTable, ref net);

            out_subcomboClusters = new List <List <string> >();
            out_simpleComboList  = new List <string>();

            if (base_cluster == null)
            {
                return;
            }

            if (config.total_mana == 0)
            {
                return;
            }

            List <List <String> > final_form = new List <List <string> >();

            List <String> comboNodes = new List <String>();

            List <String> combo = new List <String>();

            combo.Add(base_cluster.card);

            Dictionary <String, bool> markers = new Dictionary <string, Boolean>();

            List <String> giver_recruiting;
            List <String> receiver_recruiting;

            if (config.giver_inflation)
            {
                giver_recruiting = RecruitNeighbours(ref net, ref base_cluster.giver, ref config, ref cardTable, ref politic, ref giverPriorities, ref markers, ref combo);
                comboNodes.AddRange(giver_recruiting);
                combo.AddRange(giver_recruiting);
            }

            if (config.receiver_inflation)
            {
                receiver_recruiting = RecruitNeighbours(ref net, ref base_cluster.receiver, ref config, ref cardTable, ref politic, ref receiverPriorities, ref markers, ref combo);
                comboNodes.AddRange(receiver_recruiting);
                combo.AddRange(receiver_recruiting);
            }

            final_form.Add(combo);

            // Context filter
            int voidCount = 0;

            for (int i = 0; i < comboNodes.Count; i++)
            {
                if (comboNodes[i] == "")
                {
                    voidCount++;
                }
            }

            while (voidCount > 0)
            {
                comboNodes.Remove("");
                voidCount--;
            }

            while (comboNodes.Count > 0)
            {
                String current = comboNodes.First();
                comboNodes.Remove(current);
                HSCardCluster new_cluster = GenerateCardCluster(current, ref cardTable, ref net);

                combo = new List <String>();
                combo.Add(new_cluster.card);

                if (!markers.ContainsKey(current))
                {
                    markers.Add(current, true);
                }

                if (config.giver_inflation)
                {
                    giver_recruiting = RecruitNeighbours(ref net, ref new_cluster.giver, ref config, ref cardTable, ref politic, ref giverPriorities, ref markers, ref combo);
                    comboNodes.AddRange(giver_recruiting);
                    combo.AddRange(giver_recruiting);
                }

                if (config.receiver_inflation)
                {
                    receiver_recruiting = RecruitNeighbours(ref net, ref new_cluster.receiver, ref config, ref cardTable, ref politic, ref receiverPriorities, ref markers, ref combo);
                    comboNodes.AddRange(receiver_recruiting);
                    combo.AddRange(receiver_recruiting);
                }

                final_form.Add(combo);

                if (final_form.Count == config.maxCards)
                {
                    break;
                }
            }

            // Mana threshold 10 mana = 1 turn, 30 mana = 3 turns combo
            if (config.cutByManaCost)
            {
                Dictionary <String, String> keys = new Dictionary <string, string>();
                int  total_mana = 0;
                bool breaked    = false;
                foreach (List <String> key in final_form)
                {
                    foreach (String k in key)
                    {
                        String s = k.ToLower();

                        if (keys.ContainsKey(k))
                        {
                            continue;
                        }

                        int mana_cost;
                        Int32.TryParse(cardTable[s].cost, out mana_cost);
                        total_mana += mana_cost;

                        if (total_mana >= config.total_mana)
                        {
                            breaked = true;
                            break;
                        }

                        keys.Add(k, k);

                        if (keys.Count == config.maxCards)
                        {
                            breaked = true;
                            break;
                        }
                    }

                    if (breaked)
                    {
                        break;
                    }
                }
                out_simpleComboList = keys.Keys.ToList();
            }
            else
            {
                bool breaked = false;
                foreach (List <String> key in final_form)
                {
                    foreach (String k in key)
                    {
                        out_simpleComboList.Add(k);
                        if (out_simpleComboList.Count == config.maxCards)
                        {
                            breaked = true;
                            break;
                        }
                    }
                    if (breaked)
                    {
                        break;
                    }
                }
            }

            out_subcomboClusters = final_form;
        }