private Dictionary <string, string> GetRandomVillain(IEnumerable <string> availableVillains, Dictionary <string, string> promoIdentifiers)
        {
            string villain = null;

            // Choose a villain
            int villainIndex = GetRandomNumber(availableVillains.Count());

            villain = availableVillains.ElementAt(villainIndex);
            var villainDefinition = DeckDefinitionCache.GetDeckDefinition(villain);
            var villainName       = villainDefinition.Name;

            // If there is a promo, maybe choose it
            int villainPromoIndex = GetRandomNumber(1 + villainDefinition.PromoCardDefinitions.Count());

            if (villainPromoIndex > 0)
            {
                var promo = villainDefinition.PromoCardDefinitions.ElementAt(villainPromoIndex - 1);
                promoIdentifiers[villain] = promo.PromoIdentifier;
                villainName = promo.PromoTitle;
            }

            return(new Dictionary <string, string> {
                { villain, villainName }
            });
        }
        private Dictionary <string, string> GetRandomHero(List <string> availableHeroes, Dictionary <string, string> promoIdentifiers)
        {
            int index      = GetRandomNumber(availableHeroes.Count);
            var identifier = availableHeroes.ElementAt(index);
            var definition = DeckDefinitionCache.GetDeckDefinition(identifier);

            // If there is a promo, maybe choose it
            int    promoIndex = GetRandomNumber(1 + definition.PromoCardDefinitions.Count());
            string name       = definition.Name;

            if (promoIndex > 0)
            {
                var promo = definition.PromoCardDefinitions.ElementAt(promoIndex - 1);
                promoIdentifiers[identifier] = promo.PromoIdentifier;
                name = promo.PromoTitle;
            }

            return(new Dictionary <string, string> {
                { identifier, name }
            });
        }
        protected IEnumerator MakeRandomDecisions(IDecision decision)
        {
            // Make random decisions!
            if (decision is SelectCardDecision)
            {
                var selectCardDecision = (SelectCardDecision)decision;
                var choices            = selectCardDecision.Choices;
                selectCardDecision.SelectedCard = choices.ElementAtOrDefault(GetRandomNumber(choices.Count()));
            }
            else if (decision is YesNoDecision)
            {
                var yesNo = decision as YesNoDecision;
                yesNo.Answer = GetRandomNumber(1) == 1;
            }
            else if (decision is SelectDamageTypeDecision)
            {
                var damage = decision as SelectDamageTypeDecision;
                damage.SelectedDamageType = damage.Choices.ElementAtOrDefault(GetRandomNumber(damage.Choices.Count()));
            }
            else if (decision is MoveCardDecision)
            {
                var moveCard = decision as MoveCardDecision;
                moveCard.Destination = moveCard.PossibleDestinations.ElementAtOrDefault(GetRandomNumber(moveCard.PossibleDestinations.Count()));
            }
            else if (decision is UsePowerDecision)
            {
                var power = decision as UsePowerDecision;
                power.SelectedPower = power.Choices.ElementAtOrDefault(GetRandomNumber(power.Choices.Count()));
            }
            else if (decision is UseIncapacitatedAbilityDecision)
            {
                var ability = decision as UseIncapacitatedAbilityDecision;
                ability.SelectedAbility = ability.Choices.ElementAtOrDefault(GetRandomNumber(ability.Choices.Count()));
            }
            else if (decision is SelectTurnTakerDecision)
            {
                var turn = decision as SelectTurnTakerDecision;
                turn.SelectedTurnTaker = turn.Choices.ElementAtOrDefault(GetRandomNumber(turn.Choices.Count()));
            }
            else if (decision is SelectCardsDecision)
            {
                var cards = decision as SelectCardsDecision;
                cards.ReadyForNext = true;
            }
            else if (decision is SelectFunctionDecision)
            {
                var function = decision as SelectFunctionDecision;
                function.SelectedFunction = function.Choices.ElementAtOrDefault(GetRandomNumber(function.Choices.Count()));
            }
            else if (decision is SelectNumberDecision)
            {
                var number = decision as SelectNumberDecision;
                number.SelectedNumber = number.Choices.ElementAtOrDefault(GetRandomNumber(number.Choices.Count()));
            }
            else if (decision is SelectLocationDecision)
            {
                var selectLocation = decision as SelectLocationDecision;
                selectLocation.SelectedLocation = selectLocation.Choices.ElementAtOrDefault(GetRandomNumber(selectLocation.Choices.Count()));
            }
            else if (decision is ActivateAbilityDecision)
            {
                var activate = decision as ActivateAbilityDecision;
                activate.SelectedAbility = activate.Choices.ElementAtOrDefault(GetRandomNumber(activate.Choices.Count()));
            }
            else if (decision is SelectWordDecision)
            {
                var word = decision as SelectWordDecision;
                word.SelectedWord = word.Choices.ElementAtOrDefault(GetRandomNumber(word.Choices.Count()));
            }
            else if (decision is SelectFromBoxDecision)
            {
                var box               = decision as SelectFromBoxDecision;
                var heroes            = DeckDefinition.AvailableHeroes;
                var selectedTurnTaker = heroes.ElementAtOrDefault(GetRandomNumber(heroes.Count()));
                var promos            = DeckDefinitionCache.GetDeckDefinition(selectedTurnTaker).PromoCardDefinitions.Select(cd => cd.PromoIdentifier);
                var selectedPromo     = promos.ElementAtOrDefault(GetRandomNumber(promos.Count()));
                box.SelectedIdentifier          = selectedPromo;
                box.SelectedTurnTakerIdentifier = selectedTurnTaker;
            }
            else if (decision is SelectTurnPhaseDecision)
            {
                var selectPhase = decision as SelectTurnPhaseDecision;
                selectPhase.SelectedPhase = selectPhase.Choices.ElementAtOrDefault(GetRandomNumber(selectPhase.Choices.Count()));
            }
            else
            {
                Assert.Fail("Unhandled decision: " + decision);
            }

            yield return(null);
        }
        protected GameController SetupRandomGameController(bool reasonable, IEnumerable <string> availableHeroes = null, IEnumerable <string> availableVillains = null, IEnumerable <string> availableEnvironments = null,
                                                           string overrideEnvironment = null, List <string> useHeroes = null)
        {
            string environment      = overrideEnvironment;
            var    heroes           = new List <string>();
            var    promoIdentifiers = new Dictionary <string, string>();

            if (availableHeroes == null)
            {
                availableHeroes = DeckDefinition.AvailableHeroes;
            }

            if (availableVillains == null)
            {
                availableVillains = DeckDefinition.AvailableVillains;
            }

            if (availableEnvironments == null)
            {
                availableEnvironments = DeckDefinition.AvailableEnvironments;
            }

            var villainInfo = GetRandomVillain(availableVillains, promoIdentifiers);
            var villain     = villainInfo.Keys.FirstOrDefault();
            var villainName = villainInfo.Values.FirstOrDefault();

            Console.WriteLine(villainName + " threatens the Multiverse!");

            // Choose an environment
            if (environment == null)
            {
                environment = GetRandomEnvironment(availableEnvironments);
            }

            Console.WriteLine(environment + " is the location of the conflict.");

            // Choose heroes
            var heroesLeft = availableHeroes.ToList();
            int numHeroes  = GetRandomNumber(3, 6);

            while (heroes.Count < numHeroes)
            {
                string identifier = "";
                string name       = "";
                if (useHeroes != null && useHeroes.Count() > 0)
                {
                    identifier = useHeroes.First();
                    var definition = DeckDefinitionCache.GetDeckDefinition(identifier);
                    name = definition.Name;
                    useHeroes.Remove(identifier);
                }
                else
                {
                    var heroInfo = GetRandomHero(heroesLeft, promoIdentifiers);
                    identifier = heroInfo.FirstOrDefault().Key;
                    name       = heroInfo.FirstOrDefault().Value;
                }

                Console.WriteLine(name + " joins the team!");
                heroes.Add(identifier);
                heroesLeft.Remove(identifier);
            }

            bool advanced = (GetRandomNumber(2) == 1);

            List <string> identifiers = MakeGameIdentifiers(villain, heroes, environment);

            var seed = GetRandomNumber();
            var gc   = SetupGameController(identifiers, advanced, promoIdentifiers, randomSeed: seed);

            this.seededRng = gc.Game.RNG;

            gc.OnMakeDecisions -= MakeDecisions;
            if (reasonable)
            {
                gc.OnMakeDecisions += MakeSomewhatReasonableDecisions;
            }
            else
            {
                gc.OnMakeDecisions += MakeRandomDecisions;
            }

            return(gc);
        }