예제 #1
0
        public static void Kazakus()
        {
            var game = new Game(new GameConfig
            {
                StartPlayer      = 1,
                Player1HeroClass = CardClass.DRUID,
                Player1Deck      = new List <Card>()
                {
                },
                Player2HeroClass = CardClass.DRUID,
                Player2Deck      = new List <Card>()
                {
                },
                FillDecks = false
            });

            game.StartGame();
            game.Player1.BaseMana = 10;
            game.Player2.BaseMana = 10;
            var testCard = Generic.DrawCard(game.CurrentPlayer, Cards.FromName("Kazakus"));

            game.Process(PlayCardTask.Minion(game.CurrentPlayer, testCard));
            game.Process(ChooseTask.Pick(game.CurrentPlayer, game.CurrentPlayer.Choice.Choices[0]));
            game.Process(ChooseTask.Pick(game.CurrentPlayer, game.CurrentPlayer.Choice.Choices[0]));
            game.Process(ChooseTask.Pick(game.CurrentPlayer, game.CurrentPlayer.Choice.Choices[0]));

            ShowLog(game, LogLevel.VERBOSE);
        }
예제 #2
0
        static void CloneAdapt()
        {
            var game = new Game(new GameConfig
            {
                StartPlayer      = 1,
                Player1HeroClass = CardClass.DRUID,
                Player2HeroClass = CardClass.DRUID,
                FillDecks        = true
            });

            game.Player1.BaseMana = 10;
            game.Player2.BaseMana = 10;
            game.StartGame();

            var minion = Generic.DrawCard(game.CurrentPlayer, Cards.FromName("Elder Longneck"));
            var clone1 = game.Clone();
            var clone2 = game.Clone();
            var clone3 = game.Clone();
            var clone4 = game.Clone();

            game.Process(PlayCardTask.Minion(game.CurrentPlayer, game.CurrentPlayer.HandZone[4]));
            game.Process(ChooseTask.Pick(game.CurrentPlayer, game.CurrentPlayer.Choice.Choices[0]));

            clone1.Process(PlayCardTask.Minion(clone1.CurrentPlayer, clone1.CurrentPlayer.HandZone[4]));
            clone1.Process(ChooseTask.Pick(clone1.CurrentPlayer, clone1.CurrentPlayer.Choice.Choices[0]));

            clone2.Process(PlayCardTask.Minion(clone2.CurrentPlayer, clone2.CurrentPlayer.HandZone[4]));
            clone2.Process(ChooseTask.Pick(clone2.CurrentPlayer, clone2.CurrentPlayer.Choice.Choices[0]));

            clone3.Process(PlayCardTask.Minion(clone3.CurrentPlayer, clone3.CurrentPlayer.HandZone[4]));
            clone3.Process(ChooseTask.Pick(clone3.CurrentPlayer, clone3.CurrentPlayer.Choice.Choices[0]));

            clone4.Process(PlayCardTask.Minion(clone4.CurrentPlayer, clone4.CurrentPlayer.HandZone[4]));
            clone4.Process(ChooseTask.Pick(clone4.CurrentPlayer, clone4.CurrentPlayer.Choice.Choices[0]));
        }
예제 #3
0
        /// <summary>
        /// Choose Nth item from choices (the leftest one is 1)
        /// </summary>
        public static void ChooseNthChoice(this Game game, int n)
        {
            if (n > game.CurrentPlayer.Choice.Choices.Count)
            {
                throw new ArgumentOutOfRangeException();
            }

            game.Process(ChooseTask.Pick(game.CurrentPlayer, game.CurrentPlayer.Choice.Choices[n - 1]));
        }
예제 #4
0
        /// <summary>
        /// Choose Nth item from choices (the leftest one is 1)
        /// </summary>
        public static void ChooseNthChoice(this Game game, int n)
        {
            if (n > game.CurrentPlayer.Choice.Choices.Count)
            {
                throw new ArgumentOutOfRangeException();
            }
            var option = ChooseTask.Pick(game.CurrentPlayer, game.CurrentPlayer.Choice.Choices[n - 1]);

            if (!game.Process(option))
            {
                throw new Exception($"{option} is not a valid task.");
            }
        }
예제 #5
0
        public static ChooseTask CreatePlayerTaskChoice(Game game, int PlayerId, ChoiceType choiceType, List <int> entities)
        {
            switch (choiceType)
            {
            case ChoiceType.MULLIGAN:
                return(ChooseTask.Mulligan(game.Player1.PlayerId == PlayerId ? game.Player1 : game.Player2.PlayerId == PlayerId ? game.Player2 : null, entities));

            case ChoiceType.GENERAL:
                return(ChooseTask.Pick(game.CurrentPlayer, entities[0]));

            default:
                return(null);
            }
        }
예제 #6
0
        private PlayerTask ProcessPowerChoiceData(int PlayerId, ChoiceType choiceType, List <int> entities)
        {
            switch (choiceType)
            {
            case ChoiceType.MULLIGAN:
                return(ChooseTask.Mulligan(_game.Player1.PlayerId == PlayerId ? _game.Player1 : _game.Player2.PlayerId == PlayerId ? _game.Player2 : null, entities));

            case ChoiceType.GENERAL:
                return(ChooseTask.Pick(_game.CurrentPlayer, entities[0]));

            default:
                return(null);
            }
        }
예제 #7
0
        /// <summary>
        /// Choose Nth item from choices (the leftest one is 1).
        /// </summary>
        /// <returns>The chosen entity.</returns>
        public static IPlayable ChooseNthChoice(this Game game, int n)
        {
            if (n > game.CurrentPlayer.Choice.Choices.Count)
            {
                throw new ArgumentOutOfRangeException();
            }

            int        pick   = game.CurrentPlayer.Choice.Choices[n - 1];
            ChooseTask option = ChooseTask.Pick(game.CurrentPlayer, pick);

            if (!game.Process(option))
            {
                throw new Exception($"{option} is not a valid task.");
            }

            return(game.IdEntityDic[pick]);
        }
예제 #8
0
        public void OnChooseEntities(KettleChooseEntities chooseEntities)
        {
            Console.WriteLine("simulator OnChooseEntities called");

            var entityChoices = Game.EntityChoicesMap[chooseEntities.Id];
            var chooseTask    = entityChoices.ChoiceType == ChoiceType.MULLIGAN
                                ? ChooseTask.Mulligan(entityChoices.PlayerId == 1 ? Game.Player1 : Game.Player2, chooseEntities.Choices)
                                : ChooseTask.Pick(entityChoices.PlayerId == 1 ? Game.Player1 : Game.Player2, chooseEntities.Choices[0]);

            Console.WriteLine($"processing => {chooseTask.FullPrint()}");

            Adapter.SendMessage(new KettleEntitiesChosen
            {
                ChoiceType     = (int)entityChoices.ChoiceType,
                PlayerId       = entityChoices.PlayerId,
                ChooseEntities = chooseEntities,
            });

            Game.Process(chooseTask);
            ShowLog(Game, LogLevel.VERBOSE);

            SendPowerHistory(Game.PowerHistory.Last);
            SendChoicesOrOptions();

            if (Game.Step == Step.BEGIN_MULLIGAN &&
                Game.Player1.MulliganState == Mulligan.DONE &&
                Game.Player2.MulliganState == Mulligan.DONE)
            {
                Game.MainBegin();

                while (Game.Step != Step.MAIN_ACTION)
                {
                    Thread.Sleep(500);
                }

                ShowLog(Game, LogLevel.VERBOSE);

                SendPowerHistory(Game.PowerHistory.Last);
                SendChoicesOrOptions();
            }
        }
예제 #9
0
        public void OnEntityChoices(KettleEntityChoices entityChoices)
        {
            Console.WriteLine("AI EntityChoices called.");
            if (entityChoices.PlayerId != PlayerId)
            {
                return;
            }

            SabberStoneCore.Model.Entities.Controller player = PlayerId == 1 ? Session.Game.Player1 : Session.Game.Player2;
            Choice            Choice  = player.Choice;
            List <PlayerTask> options = new List <PlayerTask>();

            switch (Choice.ChoiceType)
            {
            case ChoiceType.GENERAL:
                Choice.Choices.ToList().ForEach(p => options.Add(ChooseTask.Pick(player, p)));
                break;

            case ChoiceType.MULLIGAN:
                IEnumerable <IEnumerable <int> > choices = SabberStoneCore.Model.Util.GetPowerSet(Choice.Choices);
                choices.ToList().ForEach(p => options.Add(ChooseTask.Mulligan(player, p.ToList())));
                break;

            default:
                throw new NotImplementedException();
            }

            // Do AI shit
            PlayerTask option = DoAI(options);

            // Convert it to a kettle choices
            KettleChooseEntities chooseEntities = new KettleChooseEntities();

            chooseEntities.Id      = entityChoices.Id;
            chooseEntities.Choices = ((ChooseTask)option).Choices;

            Adapter.SendMessage(chooseEntities);
        }
예제 #10
0
        public static PlayerTask GetPlayerTask(Option option, Game g)
        {
            const bool SkipPrePhase = true;
            Controller c            = g.CurrentPlayer;

            switch (option.Type)
            {
            case Choose:
                return(ChooseTask.Pick(c, option.Choice));

            case Concede:
                return(ConcedeTask.Any(c));

            case EndTurn:
                return(EndTurnTask.Any(c));

            case HeroAttack:
                return(HeroAttackTask.Any(c, GetOpponentTarget(option.TargetPosition), SkipPrePhase));

            case Option.Types.PlayerTaskType.HeroPower:
                return(HeroPowerTask.Any(c, GetTarget(option.TargetPosition), option.SubOption, SkipPrePhase));

            case MinionAttack:
                return(MinionAttackTask.Any(c, c.BoardZone[option.SourcePosition - 1], GetOpponentTarget(option.TargetPosition), SkipPrePhase));

            case PlayCard:
                IPlayable source = c.HandZone[option.SourcePosition];
                if (source.Card.Type == CardType.MINION)
                {
                    return(PlayCardTask.Any(c, source, null, option.TargetPosition - 1, option.SubOption, SkipPrePhase));
                }
                else
                {
                    return(PlayCardTask.Any(c, source, GetTarget(option.TargetPosition),
                                            0, option.SubOption, SkipPrePhase));
                }

            default:
                throw new ArgumentOutOfRangeException();
            }

            ICharacter GetOpponentTarget(int position)
            {
                if (position == Option.OP_HERO_POSITION)
                {
                    return(c.Opponent.Hero);
                }
                return(c.Opponent.BoardZone[position - 9]);
            }

            ICharacter GetTarget(int position)
            {
                if (position == -1)
                {
                    return(null);
                }
                if (position >= Option.OP_HERO_POSITION)
                {
                    return(GetOpponentTarget(position));
                }
                if (position == Option.HERO_POSITION)
                {
                    return(c.Hero);
                }
                return(c.BoardZone[position - 1]);
            }
        }
예제 #11
0
        /// <summary>
        /// Returns a set of all options this player can perform execute at the moment.
        /// From this set one option is picked and executed by the game.
        /// </summary>
        /// <param name="playCards"></param>
        /// <returns></returns>
        public List <PlayerTask> Options(bool playCards = true)
        {
            var result = new List <PlayerTask>();

            if (this != Game.CurrentPlayer)
            {
                return(result);
            }

            if (Choice != null)
            {
                switch (Choice.ChoiceType)
                {
                case ChoiceType.GENERAL:
                    Choice.Choices.ToList().ForEach(p => result.Add(ChooseTask.Pick(this, p)));
                    return(result);

                case ChoiceType.MULLIGAN:
                    IEnumerable <IEnumerable <int> > choices = Util.GetPowerSet(Choice.Choices);
                    choices.ToList().ForEach(p => result.Add(ChooseTask.Mulligan(this, p.ToList())));
                    return(result);

                default:
                    throw new NotImplementedException();
                }
            }

            // no options till mulligan is done for both players
            if (Game.Step != Step.MAIN_ACTION)
            {
                return(result);
            }

            // add end turn task ...
            result.Add(EndTurnTask.Any(this));

            if (playCards)
            {
                foreach (IPlayable playableCard in HandZone)
                {
                    var minion = playableCard as Minion;

                    if (!playableCard.IsPlayableByPlayer)
                    {
                        continue;
                    }

                    List <IPlayable> playables = playableCard.ChooseOne && !Game.CurrentPlayer.ChooseBoth
                                                ? playableCard.ChooseOnePlayables.ToList()
                                                : new List <IPlayable> {
                        playableCard
                    };

                    foreach (IPlayable t in playables)
                    {
                        if (!t.IsPlayableByCardReq)
                        {
                            continue;
                        }

                        var targets   = t.ValidPlayTargets.ToList();
                        var subResult = new List <PlayCardTask>();
                        if (!targets.Any())
                        {
                            subResult.Add(PlayCardTask.Any(this, playableCard, null, -1,
                                                           playables.Count == 1 ? 0 : playables.IndexOf(t) + 1));
                        }

                        subResult.AddRange(
                            targets.Select(
                                target =>
                                PlayCardTask.Any(this, playableCard, target, -1,
                                                 playables.Count == 1 ? 0 : playables.IndexOf(t) + 1)));

                        if (minion != null)
                        {
                            var tempSubResult = new List <PlayCardTask>();
                            int positions     = BoardZone.Count + 1;
                            for (int j = 0; j < positions; j++)
                            {
                                subResult.ForEach(p =>
                                {
                                    PlayCardTask task = p.Copy();
                                    task.ZonePosition = j;
                                    tempSubResult.Add(task);
                                });
                            }
                            subResult = tempSubResult;
                        }
                        result.AddRange(subResult);
                    }
                }
            }

            foreach (Minion minion in BoardZone)
            {
                if (!minion.CanAttack)
                {
                    continue;
                }

                IEnumerable <ICharacter> targets = minion.ValidAttackTargets;
                targets.ToList().ForEach(p => result.Add(MinionAttackTask.Any(this, minion, p)));
            }

            if (Hero.CanAttack)
            {
                IEnumerable <ICharacter> targets = Hero.ValidAttackTargets;
                targets.ToList().ForEach(p => result.Add(HeroAttackTask.Any(this, p)));
            }

            if (Hero.Power.IsPlayable)
            {
                var targets = Hero.Power.GetValidPlayTargets().ToList();
                if (targets.Any())
                {
                    targets.ToList().ForEach(p => result.Add(HeroPowerTask.Any(this, p)));
                }
                else
                {
                    result.Add(HeroPowerTask.Any(this));
                }
            }

            return(result);
        }
예제 #12
0
        public override PlayerTask GetMove(POGame game)
        {
            if (SelectHeroPower)
            {
                SelectHeroPower = false;
                List <IPlayable> choices  = game.CurrentPlayer.Choice.Choices.Select(id => game.getGame().IdEntityDic[id]).ToList();
                string           selected = HeroPowerPriorities.choose(choices.Select(c => c.Card.Name).Distinct().ToList());
                return(ChooseTask.Pick(game.CurrentPlayer, choices.First(c => c.Card.Name == selected).Id));
            }

            int mana = game.CurrentPlayer.BaseMana + game.CurrentPlayer.TemporaryMana - game.CurrentPlayer.UsedMana;
            List <PlayerTask> options         = game.CurrentPlayer.Options();
            List <PlayerTask> heroPowers      = options.Where(t => t.PlayerTaskType == PlayerTaskType.HERO_POWER).ToList();
            List <PlayerTask> playCards       = options.Where(t => t.PlayerTaskType == PlayerTaskType.PLAY_CARD && t.Source.Card.Cost <= mana).ToList();
            List <Minion>     ourMinionsReady = game.Minions.Where(m => m.Controller.Id == game.CurrentPlayer.Id && m.CanAttack).ToList();

            if (game.CurrentPlayer.MulliganState == Mulligan.INPUT)
            {
                // mulligan
                List <IPlayable> choices = game.CurrentPlayer.Choice.Choices.Select(id => game.getGame().IdEntityDic[id]).ToList();
                choices = choices.Where(c => c.Cost <= 3 && c.Card.Name != "Patches the Pirate").ToList();
                return(ChooseTask.Mulligan(game.CurrentPlayer, choices.Select(c => c.Id).ToList()));
            }
            else if (playCards.Count != 0)
            {
                // play card
                List <string> cardNames = playCards.Select(c => c.Source.Card.Name).Distinct().ToList();

                string selectedCard;
                if (game.CurrentPlayer.Hero.Weapon != null)
                {
                    // we have a weapon
                    selectedCard = CardPrioritiesWithWeapon.choose(cardNames);
                }
                else
                {
                    // we don't have a weapon
                    selectedCard = CardPrioritiesNoWeapon.choose(cardNames);
                }

                if (selectedCard == "Sir Finley Mrrgglton")
                {
                    SelectHeroPower = true;
                }

                return(playCards.First(t => t.Source.Card.Name == selectedCard));
            }
            else if (game.CurrentPlayer.Hero.CanAttack)
            {
                // hero attack
                List <Minion> enemyMinions = game.Minions.Where(m => m.Controller.Id == game.CurrentOpponent.Id).ToList();
                List <Minion> enemyTaunts  = enemyMinions.Where(m => m.HasTaunt == true).ToList();

                if (enemyTaunts.Count != 0)
                {
                    return(HeroAttackTask.Any(game.CurrentPlayer, enemyTaunts[0]));
                }
                else
                {
                    return(HeroAttackTask.Any(game.CurrentPlayer, game.CurrentOpponent.Hero));
                }
            }
            else if (ourMinionsReady.Count != 0)
            {
                // minion attack
                List <Minion> enemyMinions = game.Minions.Where(m => m.Controller.Id == game.CurrentOpponent.Id).ToList();
                List <Minion> enemyTaunts  = enemyMinions.Where(m => m.HasTaunt == true).ToList();

                if (enemyTaunts.Count != 0)
                {
                    int tauntHealth = enemyTaunts[0].Health;
                    int tauntAttack = enemyTaunts[0].AttackDamage;

                    // perfectTraders: survive the attack, kill the Taunt and don't have more overkill/wasted damage than 2
                    List <Minion> perfectTraders = ourMinionsReady.Where(m => m.Health > tauntAttack && m.AttackDamage >= tauntHealth && m.AttackDamage <= (tauntHealth + 2)).ToList();

                    // almost perfect Traders: survive the attack and kill the Taunt
                    List <Minion> almostPerfectTraders = ourMinionsReady.Where(m => m.Health > tauntAttack && m.AttackDamage >= tauntHealth).ToList();

                    // goodTraders: kill Taunt
                    List <Minion> goodTraders = ourMinionsReady.Where(m => m.AttackDamage > tauntHealth).ToList();

                    // survivingTraders: survive an attack but don't necessarily kill the taunt
                    List <Minion> survivingTraders = ourMinionsReady.Where(m => m.Health > tauntAttack).ToList();

                    // trade perfect
                    if (perfectTraders.Count != 0)
                    {
                        perfectTraders = perfectTraders.OrderBy(m => m.Health + m.AttackDamage).ToList();
                        return(MinionAttackTask.Any(game.CurrentPlayer, perfectTraders[0], enemyTaunts[0]));
                    }

                    // trade almost perfect
                    else if (almostPerfectTraders.Count != 0)
                    {
                        almostPerfectTraders = almostPerfectTraders.OrderBy(m => m.Health + m.AttackDamage).ToList();
                        return(MinionAttackTask.Any(game.CurrentPlayer, almostPerfectTraders[0], enemyTaunts[0]));
                    }

                    // trade good
                    else if (goodTraders.Count != 0)
                    {
                        // sort good traders and choose weakest to not waste potential
                        goodTraders = goodTraders.OrderBy(m => m.Health + m.AttackDamage).ToList();
                        return(MinionAttackTask.Any(game.CurrentPlayer, goodTraders[0], enemyTaunts[0]));
                    }

                    // trade so that minions survive
                    else if (survivingTraders.Count != 0)
                    {
                        return(MinionAttackTask.Any(game.CurrentPlayer, survivingTraders[0], enemyTaunts[0]));
                    }

                    // trade random
                    else
                    {
                        return(MinionAttackTask.Any(game.CurrentPlayer, ourMinionsReady[0], enemyTaunts[0]));
                    }
                }
                else
                {
                    return(MinionAttackTask.Any(game.CurrentPlayer, ourMinionsReady[0], game.CurrentOpponent.Hero));
                }
            }
            else if (mana >= 2 && heroPowers.Count != 0)
            {
                // hero power
                if (game.CurrentPlayer.Hero.HeroPower.Card.Name == "Lesser Heal" || game.CurrentPlayer.Hero.HeroPower.Card.Name == "Fireblast")
                {
                    return(options[0]);                    // end turn, because we don't know how to set the target
                }
                else
                {
                    return(heroPowers[0]);                    // use hero power
                }
            }
            else
            {
                // fallback: end turn
                return(options[0]);
            }
        }