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); }
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])); }
/// <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])); }
/// <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."); } }
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); } }
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); } }
/// <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]); }
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(); } }
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); }
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]); } }
/// <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); }
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]); } }