public bool IsComboBonus(BotBonus bonus, BotMap map)
        {
            if (bonus.Amount > 4 || IsInefficientBonus(bonus) || IsWastelandedBonus(bonus))
            {
                return(false);
            }

            ComboBonuses temp = new ComboBonuses(bonus, map);

            return(temp.isCombo);
        }
        /// <summary>
        /// Prioritizes combos or FTBs that contain less picks adjacent to the bonus. Also places Sub Combos at bottom of list with exception of counterable combos
        /// </summary>
        /// <param name="list"></param>
        private void ReorderCombosByNumberOfTerritories(ref List <ComboBonuses> list)
        {
            List <TerritoryIDType> seenPickIDs = new List <TerritoryIDType>();

            for (int i = 0; i < list.Count; i++)
            {
                if (seenPickIDs.Contains(list[i].mainPick.ID))
                {
                    continue;
                }
                else
                {
                    seenPickIDs.Add(list[i].mainPick.ID);
                    if (list[i].adjacentPickTerritories.Count < 3 && list[i].isEfficient)
                    {
                        ComboBonuses temp = list[i];
                        list.Remove(temp);
                        list.Insert(0, temp);
                    }
                }
            }

            if (list.Count > 0 && !list[0].isFTB)
            {
                List <TerritoryIDType> hasSeen = new List <TerritoryIDType>();
                for (int i = 0; i < list.Count; i++)
                {
                    if (!hasSeen.Contains(list[i].mainPick.Details.ID) && (list[i].mainBonus.Amount == 3 || GetSmallestBonus(list[i].isFTB ? list[i].supportFTBPick : list[i].supportComboPick) == 5))
                    {
                        ComboBonuses temp = list[i];
                        list.RemoveAt(i);
                        list.Add(temp);
                        hasSeen.Add(list[i].mainPick.Details.ID);
                    }
                }

                hasSeen = new List <TerritoryIDType>();
                for (int i = 0; i < list.Count; i++)
                {
                    if (!hasSeen.Contains(list[i].mainPick.Details.ID) && list[i].adjacentPickTerritories.Count > 2)
                    {
                        ComboBonuses temp = list[i];
                        list.RemoveAt(i);
                        list.Add(temp);
                        hasSeen.Add(list[i].mainPick.Details.ID);
                    }
                }
            }
        }
        /// <summary>
        /// Obtains the picks that will be used for the game. Will determine an initial score that will be used to order to picks initially, followed by finding FTBs and combos
        /// that will be interspersed based on cases outlined in tree diagram
        /// </summary>
        /// <returns>List of territory IDs of the final picks to be sent</returns>
        public List <TerritoryIDType> GetPicks()
        {
            if (BotState.Map.IsScenarioDistribution(BotState.Settings.DistributionModeID))
            {
                var us = BotState.Map.GetTerritoriesForScenario(BotState.Settings.DistributionModeID, BotState.Me.ScenarioID);
                us.RandomizeOrder();
                return(us);
            }


            int maxPicks = BotState.Settings.LimitDistributionTerritories == 0 ? BotState.Map.Territories.Count : (BotState.Settings.LimitDistributionTerritories * BotState.Players.Count(o => o.Value.State == GamePlayerState.Playing));

            var             pickableTerritories = BotState.DistributionStanding.Territories.Values.Where(o => o.OwnerPlayerID == TerritoryStanding.AvailableForDistribution).Select(o => o.ID).ToList();
            bool            isAntWastelanded    = false;
            TerritoryIDType ausID   = (TerritoryIDType)0;
            var             map     = BotMap.FromStanding(BotState, BotState.DistributionStanding);
            var             weights = pickableTerritories.ToDictionary(o => o, terrID =>
            {
                // Check if Ant is wastelanded for Aus score modifier
                map.Territories[terrID].OwnerPlayerID = BotState.Me.ID;
                if (map.Territories[terrID].Bonuses[0].Details.Name.Equals("Antarctica") && BotState.BonusPickValueCalculator.IsWastelandedBonus(map.Territories[terrID].Bonuses[0]))
                {
                    isAntWastelanded = true;
                }
                else if (map.Territories[terrID].Bonuses[0].Details.Name.Equals("Australia"))
                {
                    ausID = terrID;
                }

                // Only find value if bonus has significiant amount
                if (map.Territories[terrID].Bonuses.Count > 0)
                {
                    BotBonus bonus = map.Territories[terrID].Bonuses[0];
                    bonus.SetMyPickValueHeuristic();
                    double r = bonus.ExpansionValue;
                    return(r);
                }
                else
                {
                    return(0);
                }
            });

            // Check for if pick is in Aus
            if (!isAntWastelanded && weights.ContainsKey(ausID))
            {
                weights[ausID] -= 25;
            }

            foreach (TerritoryIDType terrID in weights.Keys)
            {
                AILog.Log("Pick Values", map.Territories[terrID].Bonuses[0] + ": " + weights[terrID]);
            }

            // Check for FTBs and assign value for Aus based on Ant Wasteland boolean
            List <ComboBonuses> firstTurnBonusList = new List <ComboBonuses>();
            List <ComboBonuses> comboList          = new List <ComboBonuses>();

            foreach (KeyValuePair <TerritoryIDType, double> pick in weights)
            {
                // Checks for FTB and combos
                if (BotState.BonusPickValueCalculator.IsFirstTurnBonus(map.Territories[pick.Key].Bonuses[0]))
                {
                    ComboBonuses newCombo = new ComboBonuses(map.Territories[pick.Key].Bonuses[0], map);
                    firstTurnBonusList.Add(newCombo);
                }
                else if (BotState.BonusPickValueCalculator.IsComboBonus(map.Territories[pick.Key].Bonuses[0], map))
                {
                    ComboBonuses newCombo = new ComboBonuses(map.Territories[pick.Key].Bonuses[0], map);
                    comboList.Add(newCombo);
                }
            }

            ReorderCombosByNumberOfTerritories(ref firstTurnBonusList);
            ReorderCombosByNumberOfTerritories(ref comboList);


            AILog.Log("Picks", "Number of FTBs: " + firstTurnBonusList.Count);
            AILog.Log("Picks", "Number of Combos: " + comboList.Count);
            AILog.Log("Picks", "FTBs found:");
            foreach (ComboBonuses ftb in firstTurnBonusList)
            {
                AILog.Log("Picks", "\tBonus: " + ftb.mainBonus.Details.Name);
                AILog.Log("Picks", "\t\t" + ftb.mainPick.Details.Name);
                for (int i = 0; i < ftb.adjacentPickTerritories.Count; i++)
                {
                    if (ftb.adjacentPickTerritories[i].Details.Name.Equals(ftb.mainPick.Details.Name))
                    {
                        continue;
                    }
                    AILog.Log("Picks", "\t\t\t" + ftb.adjacentPickTerritories[i].Details.Name);
                }
            }
            AILog.Log("Picks", "End of FTB list");
            AILog.Log("Picks", "Combos found:");

            foreach (ComboBonuses combo in comboList)
            {
                AILog.Log("Picks", "\tBonus: " + combo.mainBonus.Details.Name);
                AILog.Log("Picks", "\t\t" + combo.mainPick.Details.Name);
                for (int i = 0; i < combo.adjacentPickTerritories.Count; i++)
                {
                    if (combo.adjacentPickTerritories[i].Details.Name.Equals(combo.mainPick.Details.Name))
                    {
                        continue;
                    }
                    AILog.Log("Picks", "\t\t\t" + (combo.adjacentPickTerritories[i].Details.Name.Equals(combo.mainPick.Details.Name) ? combo.adjacentPickTerritories[++i].Details.Name : combo.adjacentPickTerritories[i].Details.Name));
                }
            }
            AILog.Log("Picks", "End of combo list");



            List <TerritoryIDType> picks = weights.OrderByDescending(o => o.Value).Take(maxPicks).Select(o => o.Key).Distinct().ToList();

            //StatefulFogRemover.PickedTerritories = picks;

            AILog.Log("Picks", "Before final reshuffle:");
            foreach (var terr in picks)
            {
                AILog.Log("Picks", "\t" + map.Territories[terr].Bonuses[0].Details.Name + ", " + map.Territories[terr].Details.Name);
            }

            ReorderPicksByCombos(firstTurnBonusList, comboList, ref picks);

            AILog.Log("Picks", "After final reshuffle:");
            foreach (var terr in picks)
            {
                AILog.Log("Picks", "\t" + map.Territories[terr].Bonuses[0].Details.Name + ", " + map.Territories[terr].Details.Name);
            }

            Memory.PickTracker.SetPickList(picks);
            BotMap storedMap = BotState.VisibleMap.GetMapCopy();

            Memory.PickTracker.pickMap = storedMap;
            return(picks);
        }
        private Boolean IsManyTurnBonus(BotBonus bonus, ComboBonuses optionalCombo = null)
        {
            IDictionary <BotTerritory, bool> seenTerritories = new Dictionary <BotTerritory, bool>();
            BotTerritory pick = null;

            foreach (BotTerritory terr in bonus.Territories)
            {
                if (terr.Armies.NumArmies == 0)
                {
                    seenTerritories[terr] = true;
                    pick = terr;
                }
            }

            if (pick == null)
            {
                return(true);
            }

            foreach (BotTerritory adjTerr in pick.Neighbors)
            {
                if (!ContainsTerritory(bonus, adjTerr))
                {
                    continue;
                }
                seenTerritories[adjTerr] = true;
                foreach (BotTerritory adjSecondTerr in adjTerr.Neighbors)
                {
                    if (!ContainsTerritory(bonus, adjSecondTerr))
                    {
                        continue;
                    }
                    seenTerritories[adjSecondTerr] = true;
                }
            }

            if (seenTerritories.Count == bonus.Territories.Count)
            {
                return(false);
            }
            else if (optionalCombo != null)
            {
                List <BotTerritory> unseenTerritories = Except(bonus, seenTerritories.Keys.ToList <BotTerritory>());
                foreach (BotTerritory terr in optionalCombo.adjacentPickTerritories)
                {
                    if (terr.Bonuses[0] == bonus)
                    {
                        continue;
                    }
                    foreach (BotTerritory adjTerr in terr.Neighbors)
                    {
                        if (unseenTerritories.Contains(adjTerr))
                        {
                            unseenTerritories.Remove(adjTerr);
                            if (unseenTerritories.Count == 0)
                            {
                                return(false);
                            }
                        }
                        foreach (BotTerritory adjSecondTerr in adjTerr.Neighbors)
                        {
                            if (unseenTerritories.Contains(adjSecondTerr))
                            {
                                unseenTerritories.Remove(adjSecondTerr);
                                if (unseenTerritories.Count == 0)
                                {
                                    return(false);
                                }
                            }
                        }
                    }
                }
            }
            return(true);
        }