public void SummonFailTest() { var game = new Game(new GameConfig { StartPlayer = 1, Player1HeroClass = CardClass.PALADIN, Player2HeroClass = CardClass.MAGE, FillDecks = true, FillDecksPredictably = true }); game.StartGame(); game.Process(EndTurnTask.Any(game.CurrentPlayer)); game.Process(EndTurnTask.Any(game.CurrentPlayer)); game.Process(HeroPowerTask.Any(game.CurrentPlayer)); game.Process(EndTurnTask.Any(game.CurrentPlayer)); game.Process(EndTurnTask.Any(game.CurrentPlayer)); game.Process(HeroPowerTask.Any(game.CurrentPlayer)); game.Process(EndTurnTask.Any(game.CurrentPlayer)); game.Process(EndTurnTask.Any(game.CurrentPlayer)); game.Process(HeroPowerTask.Any(game.CurrentPlayer)); game.Process(EndTurnTask.Any(game.CurrentPlayer)); game.Process(EndTurnTask.Any(game.CurrentPlayer)); game.Process(HeroPowerTask.Any(game.CurrentPlayer)); game.Process(EndTurnTask.Any(game.CurrentPlayer)); game.Process(EndTurnTask.Any(game.CurrentPlayer)); game.Process(HeroPowerTask.Any(game.CurrentPlayer)); game.Process(EndTurnTask.Any(game.CurrentPlayer)); game.Process(EndTurnTask.Any(game.CurrentPlayer)); game.Process(HeroPowerTask.Any(game.CurrentPlayer)); game.Process(EndTurnTask.Any(game.CurrentPlayer)); game.Process(EndTurnTask.Any(game.CurrentPlayer)); Assert.Equal(6, game.CurrentPlayer.BoardZone.Count); game.Process(HeroPowerTask.Any(game.CurrentPlayer)); game.Process(EndTurnTask.Any(game.CurrentPlayer)); game.Process(EndTurnTask.Any(game.CurrentPlayer)); Assert.Equal(7, game.CurrentPlayer.BoardZone.Count); game.Process(HeroPowerTask.Any(game.CurrentPlayer)); Assert.Equal(7, game.CurrentPlayer.BoardZone.Count); }
public void CloneAura2() { var game = new Game(new GameConfig { StartPlayer = 1, Player1HeroClass = CardClass.MAGE, Player1Deck = new List <Card> { Cards.FromName("Sorcerer's Apprentice"), Cards.FromName("Counterspell") }, Player2HeroClass = CardClass.MAGE, Player2Deck = new List <Card> { Cards.FromName("Sorcerer's Apprentice"), Cards.FromName("Counterspell"), Cards.FromName("Vaporize") }, Shuffle = false, FillDecks = false, History = false, }); game.Player1.BaseMana = 10; game.Player2.BaseMana = 10; game.StartGame(); game.Process(PlayCardTask.Any(game.CurrentPlayer, "Sorcerer's Apprentice")); game.Process(EndTurnTask.Any(game.CurrentPlayer)); game.Process(PlayCardTask.Any(game.CurrentPlayer, "Sorcerer's Apprentice")); game.Process(EndTurnTask.Any(game.CurrentPlayer)); Assert.Equal(2, game.Auras.Count); Assert.Equal(2, game.CurrentPlayer.HandZone[0].Cost); Assert.Equal(2, game.CurrentOpponent.HandZone[0].Cost); Assert.Equal(2, game.CurrentOpponent.HandZone[1].Cost); Game clone = game.Clone(); Assert.Equal(2, clone.Auras.Count); Assert.Equal(2, clone.CurrentPlayer.HandZone[0].Cost); Assert.Equal(2, clone.CurrentOpponent.HandZone[0].Cost); Assert.Equal(2, clone.CurrentOpponent.HandZone[1].Cost); clone.Process(MinionAttackTask.Any(clone.CurrentPlayer, clone.CurrentPlayer.BoardZone[0], clone.CurrentOpponent.BoardZone[0])); Assert.Empty(clone.Auras); Assert.Equal(3, clone.CurrentPlayer.HandZone[0].Cost); Assert.Equal(3, clone.CurrentOpponent.HandZone[0].Cost); Assert.Equal(3, clone.CurrentOpponent.HandZone[1].Cost); }
public void BasicHealthAuraTest3() { var game = new Game(new GameConfig { StartPlayer = 1, Player1HeroClass = CardClass.PRIEST, Player2HeroClass = CardClass.WARLOCK, FillDecks = true, FillDecksPredictably = true }); game.StartGame(); game.Player1.BaseMana = 10; game.Player2.BaseMana = 10; var minion1 = (ICharacter)Generic.DrawCard(game.Player1, Cards.FromName("Murloc Raider")); var minion2 = (ICharacter)Generic.DrawCard(game.Player1, Cards.FromName("Murloc Warleader")); IPlayable minion3 = Generic.DrawCard(game.Player1, Cards.FromName("Stormwind Champion")); IPlayable minion4 = Generic.DrawCard(game.Player1, Cards.FromName("Ironbeak Owl")); IPlayable spell1 = Generic.DrawCard(game.Player1, Cards.FromName("Power Word: Shield")); game.Process(PlayCardTask.Minion(game.CurrentPlayer, minion1)); game.Player1.UsedMana = 0; game.Process(PlayCardTask.Minion(game.CurrentPlayer, minion2)); game.Player1.UsedMana = 0; game.Process(PlayCardTask.Minion(game.CurrentPlayer, minion3)); game.Player1.UsedMana = 0; game.Process(PlayCardTask.SpellTarget(game.CurrentPlayer, spell1, minion1)); Assert.Equal(4, minion1.Health); Assert.Equal(4, minion2.Health); Assert.Equal(6, ((ICharacter)minion3).Health); game.Process(PlayCardTask.MinionTarget(game.CurrentPlayer, minion4, minion2)); Assert.Equal(4, minion1.Health); Assert.Equal(4, minion2.Health); Assert.Equal(6, ((ICharacter)minion3).Health); Assert.Equal(2, ((ICharacter)minion4).Health); game.Process(EndTurnTask.Any(game.CurrentPlayer)); IPlayable spell2 = Generic.DrawCard(game.CurrentPlayer, Cards.FromName("Hellfire")); game.Process(PlayCardTask.Spell(game.CurrentPlayer, spell2)); Assert.Equal(1, minion1.Health); Assert.Equal(1, minion2.Health); Assert.Equal(3, ((ICharacter)minion3).Health); Assert.True(((ICharacter)minion4).IsDead); }
private static void ChooseOneTest() { var game = new Game(new GameConfig { StartPlayer = 1, Player1HeroClass = CardClass.DRUID, Player1Deck = new List <Card>() { Cards.FromName("Stonetusk Boar"), Cards.FromName("Bloodfen Raptor"), Cards.FromName("Raven Idol"), Cards.FromName("Living Roots"), Cards.FromName("Druid of the Saber"), Cards.FromName("Wrath"), Cards.FromName("Power of the Wild"), }, Player2HeroClass = CardClass.DRUID, Player2Deck = new List <Card>() { Cards.FromName("Stonetusk Boar"), Cards.FromName("Bloodfen Raptor"), Cards.FromName("Raven Idol"), Cards.FromName("Living Roots"), Cards.FromName("Druid of the Saber"), Cards.FromName("Wrath"), Cards.FromName("Power of the Wild"), }, SkipMulligan = true, Shuffle = false, FillDecks = true }); game.StartGame(); game.Process(PlayCardTask.Minion(game.CurrentPlayer, game.CurrentPlayer.HandZone[0])); game.Process(EndTurnTask.Any(game.CurrentPlayer)); game.Process(PlayCardTask.Minion(game.CurrentPlayer, game.CurrentPlayer.HandZone[0])); game.Process(EndTurnTask.Any(game.CurrentPlayer)); game.Process(PlayCardTask.Minion(game.CurrentPlayer, game.CurrentPlayer.HandZone[0])); game.Process(EndTurnTask.Any(game.CurrentPlayer)); game.Process(PlayCardTask.Minion(game.CurrentPlayer, game.CurrentPlayer.HandZone[0])); game.Process(EndTurnTask.Any(game.CurrentPlayer)); var options = game.CurrentPlayer.Options(); Console.WriteLine($" *** - {game.CurrentPlayer.Name} options on {game.Turn}. - ***"); options.ForEach(p => Console.WriteLine(p.FullPrint())); Console.WriteLine($" *** - PowerOptions - ***"); Console.WriteLine(PowerOptionsBuilder.AllOptions(game, options)?.Print()); //ShowLog(game, LogLevel.VERBOSE); }
public static void AuraTimingTest() { var game = new Game(new GameConfig { StartPlayer = 1, Player1HeroClass = CardClass.PALADIN, Player2HeroClass = CardClass.HUNTER, Player1Deck = new List <Card> { Cards.FromName("Stormwind Champion") }, Player2Deck = new List <Card> { Cards.FromName("Fiery Bat") }, FillDecks = false, Shuffle = false }); game.Player1.BaseMana = 10; game.StartGame(); game.Process(PlayCardTask.Any(game.CurrentPlayer, "Stormwind Champion")); game.CurrentPlayer.BoardZone[0].Damage = 4; game.Process(HeroPowerTask.Any(game.CurrentPlayer)); Assert.Equal(2, game.CurrentPlayer.BoardZone[1].Health); game.Process(EndTurnTask.Any(game.CurrentPlayer)); game.Process(PlayCardTask.Any(game.CurrentPlayer, "Fiery Bat")); game.CurrentPlayer.BoardZone[0].IsExhausted = false; while (true) { Game clone = game.Clone(); Assert.Equal(2, clone.CurrentOpponent.BoardZone[1].Health); clone.Process(MinionAttackTask.Any(clone.CurrentPlayer, clone.CurrentPlayer.BoardZone[0], clone.CurrentOpponent.BoardZone[0])); if (clone.CurrentOpponent.Hero.Damage == 7) { continue; } Assert.Equal(1, clone.CurrentOpponent.BoardZone.Count); Assert.Equal(1, clone.CurrentOpponent.BoardZone[0].AttackDamage); Assert.Equal(1, clone.CurrentOpponent.BoardZone[0].Health); break; } }
public void FatigueTest() { var game = new Game(new GameConfig { StartPlayer = 1, FillDecks = true, FillDecksPredictably = true }); game.StartGame(); while (game.State != State.COMPLETE) { game.Process(EndTurnTask.Any(game.CurrentPlayer)); } Assert.Equal(PlayState.WON, game.Player1.PlayState); // Fatigue test didn't worked as it should for player 1 Assert.Equal(PlayState.LOST, game.Player2.PlayState); // Fatigue test didn't worked as it should for player 2 }
public override PlayerTask GetMove(POGame poGame) { int myPlayerId = poGame.CurrentPlayer.PlayerId; List <PlayerTask> options = poGame.CurrentPlayer.Options(); // Implement a simple Mulligan Rule if (poGame.CurrentPlayer.MulliganState == Mulligan.INPUT) { List <int> mulligan = new AggroScore().MulliganRule().Invoke(poGame.CurrentPlayer.Choice.Choices.Select(p => poGame.getGame().IdEntityDic[p]).ToList()); //all mulligan handlers are the same for each score return(ChooseTask.Mulligan(poGame.CurrentPlayer, mulligan)); } var simulationResults = poGame.Simulate(options); double bestWorth = getWorth(poGame, myPlayerId); //best worth starts with the current field PlayerTask bestTask = null; foreach (PlayerTask t in options) { double resultingWorth = Double.NegativeInfinity; if (simulationResults.ContainsKey(t) && t.PlayerTaskType != PlayerTaskType.END_TURN) { POGame resultingGameState = simulationResults[t]; resultingWorth = getWorth(resultingGameState, myPlayerId); } else //TODO: think of something to do if the key is unvalid //for now, do nothing if the resulting value is negative { } if (bestWorth < resultingWorth) { bestWorth = resultingWorth; bestTask = t; } } if (bestTask == null) { return(EndTurnTask.Any(poGame.CurrentPlayer)); } return(bestTask); }
public void SecretActivation() { var game = new Game(new GameConfig { StartPlayer = 1, Player1HeroClass = CardClass.HUNTER, Player2HeroClass = CardClass.ROGUE, FillDecks = true, FillDecksPredictably = true }); game.StartGame(); game.Player1.BaseMana = 10; game.Player2.BaseMana = 10; IPlayable minion1 = Generic.DrawCard(game.CurrentPlayer, Cards.FromName("Knife Juggler")); game.Process(PlayCardTask.Minion(game.CurrentPlayer, minion1)); IPlayable testCard = Generic.DrawCard(game.CurrentPlayer, Cards.FromName("Snake Trap")); // Spawns 3 game.Process(PlayCardTask.Spell(game.CurrentPlayer, testCard)); game.Process(EndTurnTask.Any(game.CurrentPlayer)); IPlayable minion2 = Generic.DrawCard(game.CurrentPlayer, Cards.FromName("Stonetusk Boar")); game.Process(PlayCardTask.Minion(game.CurrentPlayer, minion2)); game.Process(MinionAttackTask.Any(game.CurrentPlayer, minion2, minion1)); Assert.Equal(4, game.CurrentOpponent.BoardZone.Count); if (game.CurrentPlayer.BoardZone.Count == 0) { // Minion was destroyed, so it's moved to graveyard with tags reset. Assert.Equal(1, game.CurrentPlayer.GraveyardZone.Count); Assert.Equal(game.CurrentOpponent.Hero.BaseHealth, game.CurrentOpponent.Hero.Health); Assert.Equal(game.CurrentPlayer.Hero.BaseHealth - 2, game.CurrentPlayer.Hero.Health); } else { // Minion was NOT destroyed, so it continued it's attack. Assert.Equal(0, game.CurrentPlayer.GraveyardZone.Count); Assert.Equal(game.CurrentOpponent.Hero.BaseHealth - 1, game.CurrentOpponent.Hero.Health); Assert.Equal(game.CurrentPlayer.Hero.BaseHealth - 3, game.CurrentPlayer.Hero.Health); } }
public void BasicHealthAuraTest2() { var game = new Game(new GameConfig { StartPlayer = 1, FillDecks = true, FillDecksPredictably = true }); game.StartGame(); game.Player1.BaseMana = 10; var minion1 = (ICharacter)Generic.DrawCard(game.Player1, Cards.FromName("Murloc Raider")); IPlayable minion2 = Generic.DrawCard(game.Player1, Cards.FromName("Ironbeak Owl")); IPlayable spell1 = Generic.DrawCard(game.Player1, Cards.FromName("Power Word: Shield")); game.Process(PlayCardTask.Minion(game.CurrentPlayer, minion1)); game.Process(PlayCardTask.SpellTarget(game.CurrentPlayer, spell1, minion1)); Assert.Equal(3, minion1.Health); game.Process(PlayCardTask.MinionTarget(game.CurrentPlayer, minion2, minion1)); Assert.Equal(1, minion1.Health); game.Process(EndTurnTask.Any(game.CurrentPlayer)); game.Process(EndTurnTask.Any(game.CurrentPlayer)); var minion3 = (ICharacter)Generic.DrawCard(game.Player1, Cards.FromName("Bloodfen Raptor")); IPlayable minion4 = Generic.DrawCard(game.Player1, Cards.FromName("Ironbeak Owl")); IPlayable spell2 = Generic.DrawCard(game.Player1, Cards.FromName("Power Word: Shield")); game.Process(PlayCardTask.Minion(game.CurrentPlayer, minion3)); game.Process(PlayCardTask.SpellTarget(game.CurrentPlayer, spell2, minion3)); Assert.Equal(4, minion3.Health); ((Minion)minion3).Damage = 3; game.Process(PlayCardTask.MinionTarget(game.CurrentPlayer, minion4, minion3)); Assert.Equal(1, minion3.Health); }
public void BlackwingCorruptor_BRM_034() { var game = new Game(new GameConfig { StartPlayer = 1, Player1HeroClass = CardClass.PRIEST, DeckPlayer1 = new List <Card>() { Cards.FromName("Azure Drake"), Cards.FromName("Blackwing Corruptor"), Cards.FromName("Stonetusk Boar"), Cards.FromName("Stonetusk Boar"), Cards.FromName("Bloodfen Raptor"), Cards.FromName("Bloodfen Raptor") }, Player2HeroClass = CardClass.PRIEST, DeckPlayer2 = new List <Card>() { Cards.FromName("Blackwing Corruptor"), Cards.FromName("Stonetusk Boar"), Cards.FromName("Stonetusk Boar"), Cards.FromName("Bloodfen Raptor"), Cards.FromName("Bloodfen Raptor") }, FillDecks = false, Shuffle = false }); game.StartGame(); game.Player1.BaseMana = 10; game.Player2.BaseMana = 10; var testCard1 = Generic.DrawCard(game.CurrentPlayer, Cards.FromName("Blackwing Corruptor")); game.Process(PlayCardTask.MinionTarget(game.CurrentPlayer, testCard1, game.CurrentOpponent.Hero)); game.Process(EndTurnTask.Any(game.CurrentPlayer)); var testCard2 = Generic.DrawCard(game.CurrentPlayer, Cards.FromName("Blackwing Corruptor")); game.Process(PlayCardTask.Minion(game.CurrentPlayer, testCard2)); Assert.AreEqual(1, game.Player1.Board.Count); Assert.AreEqual(1, game.Player2.Board.Count); Assert.AreEqual(30, game.Player1.Hero.Health); Assert.AreEqual(27, game.Player2.Hero.Health); }
public override PlayerTask GetMove(POGame poGame) { // start stop watch if (!Watch.IsRunning) { Watch.Start(); } // calculate a new bunch of solutions if (_currentSolutions == null) { _currentSolutions = new Queue <PlayerTask>(); } Controller currentPlayer = poGame.CurrentPlayer; if (_currentSolutions != null && _currentSolutions.Count < 1) { List <PlayerTask> solutions = GetSolutions(poGame, currentPlayer.Id, _scoring); foreach (PlayerTask solution in solutions) { _currentSolutions.Enqueue(solution); } } PlayerTask result = _currentSolutions.Dequeue(); if (result.PlayerTaskType == PlayerTaskType.CHOOSE && poGame.CurrentPlayer.Choice == null) { result = EndTurnTask.Any(currentPlayer); } // reset watch if (result.PlayerTaskType == PlayerTaskType.END_TURN || poGame.State == SabberStoneCore.Enums.State.COMPLETE || poGame.State == SabberStoneCore.Enums.State.INVALID) { Watch.Reset(); } return(result); }
public static void CardsTest() { var game = new Game(new GameConfig { StartPlayer = 1, Player1HeroClass = CardClass.WARLOCK, Player1Deck = new List <Card>() { Cards.FromName("Bloodreaver Gul'dan") }, Player2HeroClass = CardClass.MAGE, Shuffle = false, FillDecks = true, FillDecksPredictably = true }); game.StartGame(); game.Player1.BaseMana = 10; game.Player2.BaseMana = 10; game.Process(EndTurnTask.Any(game.CurrentPlayer)); game.Process(HeroPowerTask.Any(game.CurrentPlayer, game.CurrentOpponent.Hero)); game.Process(EndTurnTask.Any(game.CurrentPlayer)); game.Process(EndTurnTask.Any(game.CurrentPlayer)); game.Process(HeroPowerTask.Any(game.CurrentPlayer, game.CurrentOpponent.Hero)); game.Process(EndTurnTask.Any(game.CurrentPlayer)); game.Process(PlayCardTask.Any(game.CurrentPlayer, "Bloodreaver Gul'dan")); game.Process(EndTurnTask.Any(game.CurrentPlayer)); game.Process(HeroPowerTask.Any(game.CurrentPlayer, game.CurrentOpponent.Hero)); game.Process(EndTurnTask.Any(game.CurrentPlayer)); ShowLog(game, LogLevel.VERBOSE); //Console.WriteLine(game.CurrentPlayer.BoardZone.FullPrint()); //Console.WriteLine(game.CurrentPlayer.HandZone.FullPrint()); //Console.WriteLine(game.CurrentPlayer.DeckZone.FullPrint()); }
/// <inheritdoc /> public SabberStoneAction Sample(SabberStoneState state, OddmentTable <SabberStonePlayerTask> sideInformation) { var copyState = (SabberStoneState)state.Copy(); var availableTasks = GetAvailablePlayerTasks(copyState); var action = new SabberStoneAction(); var tries = 0; // Keep sampling tasks while we have not passed the turn yet and there are more tasks available than only EndTurn or HeroPower, of if we haven't generated a suitable task in 100 tries while (!action.IsComplete() && availableTasks.Any(i => i.Task.PlayerTaskType != PlayerTaskType.END_TURN && i.Task.PlayerTaskType != PlayerTaskType.HERO_POWER) && tries < 100) { // Sample a task from the OddmentTable var task = sideInformation.Next(); // Check if the task is available in the current state if (!availableTasks.Contains(task, PlayerTaskComparer.Comparer)) { tries++; continue; } tries = 0; action.AddTask(task); copyState.Game.Process(task.Task); availableTasks = GetAvailablePlayerTasks(copyState); } if (action.IsComplete()) { return(action); } // If hero power is available, add it if (availableTasks.Any(i => i.Task.PlayerTaskType == PlayerTaskType.HERO_POWER)) { action.AddTask(availableTasks.First(i => i.Task.PlayerTaskType == PlayerTaskType.HERO_POWER)); } // If the action is not complete yet, add EndTurn action.AddTask((SabberStonePlayerTask)EndTurnTask.Any(state.Game.CurrentPlayer)); return(action); }
public void SecretOrderOfPlay() { var game = new Game(new GameConfig { StartPlayer = 1, Player1HeroClass = CardClass.MAGE, Player1Deck = new List <Card>() { Cards.FromName("Vaporize"), Cards.FromName("Ice Barrier"), Cards.FromName("Stonetusk Boar") }, Player2HeroClass = CardClass.HUNTER, Player2Deck = new List <Card>() { Cards.FromName("Stonetusk Boar"), Cards.FromName("Freezing Trap"), Cards.FromName("Explosive Trap") }, Shuffle = false, FillDecks = true, FillDecksPredictably = true }); game.StartGame(); game.Player1.BaseMana = 10; game.Player2.BaseMana = 10; game.Process(PlayCardTask.Spell(game.CurrentPlayer, "Vaporize")); game.Process(PlayCardTask.Spell(game.CurrentPlayer, "Ice Barrier")); game.Process(EndTurnTask.Any(game.CurrentPlayer)); game.Process(PlayCardTask.Minion(game.CurrentPlayer, "Stonetusk Boar")); game.Process(MinionAttackTask.Any(game.CurrentPlayer, game.CurrentPlayer.BoardZone[0], game.CurrentOpponent.Hero)); Assert.Equal(8, game.CurrentOpponent.Hero.Armor); game.Process(PlayCardTask.Spell(game.CurrentPlayer, "Freezing Trap")); game.Process(PlayCardTask.Spell(game.CurrentPlayer, "Explosive Trap")); game.Process(EndTurnTask.Any(game.CurrentPlayer)); game.Process(PlayCardTask.Minion(game.CurrentPlayer, "Stonetusk Boar")); game.Process(MinionAttackTask.Any(game.CurrentPlayer, game.CurrentPlayer.BoardZone[0], game.CurrentOpponent.Hero)); Assert.Equal(30, game.CurrentOpponent.Hero.Health); }
/// <summary> /// Determines the best tasks for the game state based on the provided statistics and creates a <see cref="SabberStoneAction"/> from them. /// </summary> /// <param name="state">The game state to create the best action for.</param> /// <returns><see cref="SabberStoneAction"/> created from the best individual tasks available in the provided state.</returns> public SabberStoneAction DetermineBestTasks(SabberStoneState state) { // Clone game so that we can process the selected tasks and get an updated options list. var clonedGame = state.Game.Clone(); // We have to determine which tasks are the best to execute in this state, based on the provided values of the MCTS search. // So we'll check the statistics table for the highest value among tasks that are currently available in the state. // This continues until the end-turn task is selected. var action = new SabberStoneAction(); while (!action.IsComplete() && clonedGame.State != State.COMPLETE) { // Get the available options in this state and find which tasks we have statistics on, but ignore the END-TURN task for now var availableTasks = clonedGame.CurrentPlayer.Options().Where(i => i.PlayerTaskType != PlayerTaskType.END_TURN).Select(i => ((SabberStonePlayerTask)i).GetHashCode()); var stats = TaskStatistics.Where(i => availableTasks.Contains(i.Key)).ToList(); var bestTask = stats.OrderByDescending(i => i.Value.AverageValue()).FirstOrDefault(); // If we can't find any task, stop. if (bestTask.IsDefault()) { // End the turn action.AddTask((SabberStonePlayerTask)EndTurnTask.Any(clonedGame.CurrentPlayer)); break; } // Handle the possibility of tasks with tied average value. var bestValue = bestTask.Value.AverageValue(); var tiedTasks = stats.Where(i => Math.Abs(i.Value.AverageValue() - bestValue) < Constants.DOUBLE_EQUALITY_TOLERANCE); var orderedTies = tiedTasks.OrderByDescending(i => i.Value.Visits); bestTask = orderedTies.First(); // If we found a task, add it to the Action and process it to progress the game. var task = bestTask.Value.Task; action.AddTask(task); clonedGame.Process(task.Task); } // Return the created action consisting of the best action available at each point. return(action); }
public static void TransformationInHand() { var game = new Game(new GameConfig { StartPlayer = 1, FillDecks = true, FillDecksPredictably = true, Shuffle = false, }); game.StartGame(); IPlayable blade = Generic.DrawCard(game.Player1, Cards.FromName("Molten Blade")); IPlayable scroll = Generic.DrawCard(game.Player1, Cards.FromName("Shifting Scroll")); IPlayable zerus = Generic.DrawCard(game.Player1, Cards.FromName("Shifter Zerus")); game.Process(EndTurnTask.Any(game.CurrentPlayer)); game.Process(EndTurnTask.Any(game.CurrentPlayer)); // Next Turn Assert.Equal(blade.Cost, blade.Card.Cost); Assert.Equal(scroll.Cost, scroll.Card.Cost); if (zerus.AuraEffects != null) { Assert.Equal(zerus.Cost, zerus.Card.Cost); } game.Process(EndTurnTask.Any(game.CurrentPlayer)); game.Process(EndTurnTask.Any(game.CurrentPlayer)); // Next Turn Assert.Equal(blade.Cost, blade.Card.Cost); Assert.Equal(scroll.Cost, scroll.Card.Cost); if (zerus.AuraEffects != null) { Assert.Equal(zerus.Cost, zerus.Card.Cost); } Assert.Equal(zerus.Cost, zerus.Card.Cost); }
public void EmperorThaurissan_BRM_028() { var game = new Game(new GameConfig { StartPlayer = 1, Player1HeroClass = CardClass.MAGE, Player2HeroClass = CardClass.MAGE, FillDecks = true }); game.StartGame(); game.Player1.BaseMana = 10; game.Player2.BaseMana = 10; var testCard = Generic.DrawCard(game.CurrentPlayer, Cards.FromName("Emperor Thaurissan")); game.Process(PlayCardTask.Minion(game.CurrentPlayer, testCard)); var totCost = game.CurrentPlayer.Hand.GetAll.Sum(p => p.Cost); Assert.AreEqual(4, game.CurrentPlayer.Hand.Count); game.Process(EndTurnTask.Any(game.CurrentPlayer)); Assert.AreEqual(totCost - 4, game.CurrentOpponent.Hand.GetAll.Sum(p => p.Cost)); }
public void SylvanasWindrunner_EX1_016() { var game = new Game(new GameConfig { StartPlayer = 1, Player1HeroClass = CardClass.WARLOCK, Player2HeroClass = CardClass.MAGE, FillDecks = true, FillDecksPredictably = true }); game.StartGame(); game.Player1.BaseMana = 10; game.Player2.BaseMana = 10; IPlayable minion11 = Generic.DrawCard(game.CurrentPlayer, Cards.FromName("Bloodfen Raptor")); game.Process(PlayCardTask.Minion(game.CurrentPlayer, minion11)); IPlayable minion12 = Generic.DrawCard(game.CurrentPlayer, Cards.FromName("Leper Gnome")); game.Process(PlayCardTask.Minion(game.CurrentPlayer, minion12)); game.Process(EndTurnTask.Any(game.CurrentPlayer)); var minion2 = (ICharacter)Generic.DrawCard(game.CurrentPlayer, Cards.FromName("Sylvanas Windrunner")); game.Process(PlayCardTask.Minion(game.CurrentPlayer, minion2)); int myBoardCount = game.CurrentPlayer.BoardZone.Count; int opBoardCount = game.CurrentOpponent.BoardZone.Count; IPlayable spell1 = Generic.DrawCard(game.CurrentPlayer, Cards.FromName("Fireball")); game.Process(PlayCardTask.SpellTarget(game.CurrentPlayer, spell1, minion2)); Assert.Equal(myBoardCount, game.CurrentPlayer.BoardZone.Count); Assert.Equal(opBoardCount - 1, game.CurrentOpponent.BoardZone.Count); }
public void Vanish_NEW1_004() { var game = new Game(new GameConfig { StartPlayer = 1, Player1HeroClass = CardClass.ROGUE, Player2HeroClass = CardClass.ROGUE, FillDecks = true, FillDecksPredictably = true }); game.StartGame(); game.Player1.BaseMana = 10; game.Player2.BaseMana = 10; int player1HandCount = game.CurrentPlayer.HandZone.Count; Assert.Equal(0, game.CurrentPlayer.BoardZone.Count); // player 1 plays 7 minions for (int i = 0; i < 7; i++) { IPlayable minion = Generic.DrawCard(game.CurrentPlayer, Cards.FromName("Wisp")); game.Process(PlayCardTask.Minion(game.CurrentPlayer, minion)); } Assert.Equal(7, game.CurrentPlayer.BoardZone.Count); // end turn game.Process(EndTurnTask.Any(game.CurrentPlayer)); // player 2 plays vanish IPlayable spell = Generic.DrawCard(game.CurrentPlayer, Cards.FromName("Vanish")); game.Process(PlayCardTask.Spell(game.CurrentPlayer, spell)); Assert.Equal(0, game.CurrentPlayer.Opponent.BoardZone.Count); Assert.Equal(10, game.CurrentPlayer.Opponent.HandZone.Count); }
public void NerubianEgg_FP1_007() { var game = new Game(new GameConfig { StartPlayer = 1, Player1HeroClass = CardClass.MAGE, Player2HeroClass = CardClass.MAGE, FillDecks = true, FillDecksPredictably = true }); game.StartGame(); game.Player1.BaseMana = 10; game.Player2.BaseMana = 10; SabberStoneCore.Model.Entities.IPlayable testCard = Generic.DrawCard(game.CurrentPlayer, Cards.FromName("Nerubian Egg")); game.Process(PlayCardTask.Minion(game.CurrentPlayer, testCard)); game.Process(EndTurnTask.Any(game.CurrentPlayer)); SabberStoneCore.Model.Entities.IPlayable spell = Generic.DrawCard(game.CurrentPlayer, Cards.FromName("Fireball")); game.Process(PlayCardTask.SpellTarget(game.CurrentPlayer, spell, testCard)); Assert.Equal(1, game.CurrentOpponent.BoardZone.Count); Assert.Equal("FP1_007t", game.CurrentOpponent.BoardZone[0].Card.Id); }
public static void CardsTest() { var game = new Game(new GameConfig { StartPlayer = 1, Player1HeroClass = CardClass.PRIEST, Player1Deck = new List <Card> { Cards.FromName("Murloc Raider"), Cards.FromName("Murloc Raider"), Cards.FromName("Murloc Tidehunter"), Cards.FromName("Murloc Tidehunter"), Cards.FromName("Herald Volazj"), }, Player2HeroClass = CardClass.PRIEST, FillDecks = false, Shuffle = false }); game.StartGame(); game.Player1.BaseMana = 10; game.Player2.BaseMana = 10; game.Process(PlayCardTask.Minion(game.CurrentPlayer, game.CurrentPlayer.HandZone[0])); // Murloc Raider game.Process(PlayCardTask.Minion(game.CurrentPlayer, game.CurrentPlayer.HandZone[0])); // Murloc Raider game.Process(PlayCardTask.Minion(game.CurrentPlayer, game.CurrentPlayer.HandZone[0])); // Murloc Tidehunter game.Process(PlayCardTask.Minion(game.CurrentPlayer, game.CurrentPlayer.HandZone[0])); // Murloc Tidehunter game.Process(EndTurnTask.Any(game.CurrentPlayer)); game.Process(EndTurnTask.Any(game.CurrentPlayer)); game.Process(PlayCardTask.Minion(game.CurrentPlayer, game.CurrentPlayer.HandZone[0])); // Herald Volazj ShowLog(game, LogLevel.VERBOSE); Console.WriteLine(game.CurrentPlayer.BoardZone.FullPrint()); Console.WriteLine(game.CurrentPlayer.HandZone.FullPrint()); Console.WriteLine(game.CurrentPlayer.DeckZone.FullPrint()); }
/// <summary> /// Applies a SabberStoneAction to a SabberStoneState which results in a new SabberStoneState. /// </summary> /// <param name="context">The context of the search.</param> /// <param name="position">The state to which the action should be applied.</param> /// <param name="action">The action to apply.</param> /// <returns>SabberStoneState that is the result of applying the action.</returns> public SabberStoneState Apply(SearchContext <List <SabberStoneAction>, SabberStoneState, SabberStoneAction, object, SabberStoneAction> context, SabberStoneState position, SabberStoneAction action) { // In case of hierarchical expansion, we'll arrive here with incomplete actions, i.e. actions that might not have end-turn tasks. // We'll still have to process these actions to move the state into a new state, ready for further expansion. // Check if the action is complete, or if we are applying Hierarchical Expansion (in that case the action will be incomplete). if (action.IsComplete() || HierarchicalExpansion) { // Process each task. foreach (var item in action.Tasks) { position.Game.Process(item.Task); } } else { // In the case of an incomplete action, just pass the turn. position.Game.Process(EndTurnTask.Any(position.Game.CurrentPlayer)); } // Return the position. return(position); }
protected override List <PlayerTask> GetSolutions(POGame game, int playerId, IScore scoring) { // lazily instantiate if (_simulator == null) { //_simulator = new MCTSSimulator(_mctsParameters, _predictionParameters, // playerID, scoring, _map) //{ // Watch = Watch //}; _simulator = InitSimulator(playerId, scoring); } if (Watch.Elapsed.TotalMilliseconds <= (_mctsParameters.SimulationTime - _mctsParameters.AggregationTime)) { return(_simulator.Simulate(game).GetSolution()); } // safety net, when everything goes wrong return(new List <PlayerTask> { EndTurnTask.Any(game.CurrentPlayer) }); }
public void PowerOverwhelming_EX1_316() { var game = new Game(new GameConfig { StartPlayer = 1, Player1HeroClass = CardClass.WARLOCK, Player2HeroClass = CardClass.WARLOCK, FillDecks = true }); game.StartGame(); game.Player1.BaseMana = 10; game.Player2.BaseMana = 10; var testCard = Generic.DrawCard(game.CurrentPlayer, Cards.FromName("Power Overwhelming")); var minion = Generic.DrawCard(game.CurrentPlayer, Cards.FromName("Stonetusk Boar")); game.Process(PlayCardTask.Minion(game.CurrentPlayer, minion)); game.Process(PlayCardTask.SpellTarget(game.CurrentPlayer, testCard, minion)); Assert.AreEqual(5, ((Minion)minion).AttackDamage); Assert.AreEqual(5, ((Minion)minion).Health); game.Process(EndTurnTask.Any(game.CurrentPlayer)); Assert.AreEqual(true, minion.ToBeDestroyed); }
public void LavaShock_BRM_011() { var game = new Game(new GameConfig { StartPlayer = 1, Player1HeroClass = CardClass.SHAMAN, Player2HeroClass = CardClass.SHAMAN, FillDecks = true }); game.StartGame(); game.Player1.BaseMana = 5; game.Player2.BaseMana = 5; var testCard = Generic.DrawCard(game.CurrentPlayer, Cards.FromName("Lava Shock")); var spell = Generic.DrawCard(game.CurrentPlayer, Cards.FromName("Ancestral Knowledge")); game.Process(PlayCardTask.Spell(game.CurrentPlayer, spell)); game.Process(EndTurnTask.Any(game.CurrentPlayer)); game.Process(EndTurnTask.Any(game.CurrentPlayer)); Assert.AreEqual(4, game.CurrentPlayer.RemainingMana); game.Process(PlayCardTask.SpellTarget(game.CurrentPlayer, testCard, game.CurrentOpponent.Hero)); Assert.AreEqual(4, game.CurrentPlayer.RemainingMana); Assert.AreEqual(28, game.CurrentOpponent.Hero.Health); }
/// <inheritdoc /> public SabberStoneAction Act(SabberStoneState state) { var timer = Stopwatch.StartNew(); var stateCopy = (SabberStoneState)state.Copy(); if (_debug) { Console.WriteLine(); } if (_debug) { Console.WriteLine(Name()); } if (_debug) { Console.WriteLine($"Starting an LSI search in turn {(stateCopy.Game.Turn + 1) / 2}"); } // Create a new LSI search var search = new LSI <List <SabberStoneAction>, SabberStoneState, SabberStoneAction, object, TreeSearchNode <SabberStoneState, SabberStoneAction>, OddmentTable <SabberStonePlayerTask> >( SideInformationStrategy, SamplingStrategy, Playout, Evaluation, GameLogic, BudgetEstimationStrategy ); // Reset the solutions collection EnsembleSolutions = new List <SabberStoneAction>(); // Create a SearchContext that just holds the current state as Source and the Search. var context = SearchContext <List <SabberStoneAction>, SabberStoneState, SabberStoneAction, object, SabberStoneAction> .Context(EnsembleSolutions, stateCopy, null, null, search, null); // The Playout strategy will call the Goal strategy from the context, so we set it here context.Goal = Goal; // Execute the search Ensemble.EnsembleSearch(context, Searcher.Search, EnsembleSize); SamplesSpent = EnsembleSolutions.Sum(i => i.BudgetUsed); // Determine a solution var solution = Searcher.VoteForSolution(EnsembleSolutions, state); timer.Stop(); if (_debug) { Console.WriteLine(); } if (_debug) { Console.WriteLine($"LSI returned with solution: {solution}"); } if (_debug) { Console.WriteLine($"My total calculation time was: {timer.ElapsedMilliseconds}ms"); } // Check if the solution is a complete action. if (!solution.IsComplete()) { // Otherwise add an End-Turn task before returning. solution.Tasks.Add((SabberStonePlayerTask)EndTurnTask.Any(Player)); } // If we are estimating the budget by using the previous search's results, save these now if (BudgetEstimation == BudgetEstimationType.PreviousSearchAverage && BudgetEstimationStrategy is PreviousSearchAverageBudgetEstimationStrategy estimationStrategy) { estimationStrategy.PreviousSearchTime = timer.ElapsedMilliseconds; estimationStrategy.PreviousSearchIterations = SamplesSpent; } if (_debug) { Console.WriteLine(); } return(solution); }
public static void GameSplitTest() { Game game = null; bool goOnFlag = true; while (goOnFlag) { game = new Game(new GameConfig { StartPlayer = 1, Player1HeroClass = CardClass.PRIEST, Player1Deck = new List <Card>() { Cards.FromName("Loot Hoarder"), // 1 Cards.FromName("Loot Hoarder"), // 2 Cards.FromName("Huge Toad"), // 3 Cards.FromName("Mad Bomber"), // 4 Cards.FromName("Stonetusk Boar"), // 5 Cards.FromName("Magma Rager"), // 6 Cards.FromName("War Golem"), // 7 Cards.FromName("Reckless Rocketeer"), // 8 Cards.FromName("Wolfrider"), // 9 Cards.FromName("Sen'jin Shieldmasta"), // 10 Cards.FromName("Voodoo Doctor"), // 11 Cards.FromName("River Crocolisk"), // 12 Cards.FromName("Oasis Snapjaw"), // 13 Cards.FromName("Novice Engineer"), // 14 Cards.FromName("Core Hound"), // 15 Cards.FromName("Booty Bay Bodyguard"), // 16 Cards.FromName("Ogre Magi"), // 17 Cards.FromName("Chillwind Yeti"), // 18 Cards.FromName("Acidic Swamp Ooze"), // 19 Cards.FromName("Ironfur Grizzly"), // 20 Cards.FromName("Bluegill Warrior"), // 21 Cards.FromName("Murloc Tidehunter"), // 22 Cards.FromName("Frostwolf Grunt"), // 23 Cards.FromName("Ironforge Rifleman"), // 24 Cards.FromName("Kobold Geomancer"), // 25 Cards.FromName("Razorfen Hunter"), // 26 Cards.FromName("Gnomish Inventor"), // 27 Cards.FromName("Stormwind Knight"), // 28 Cards.FromName("Gurubashi Berserker"), // 29 Cards.FromName("Elven Archer"), // 30 }, Player2HeroClass = CardClass.HUNTER, Player2Deck = new List <Card>() { Cards.FromName("Loot Hoarder"), // 1 Cards.FromName("Loot Hoarder"), // 2 Cards.FromName("Huge Toad"), // 3 Cards.FromName("Mad Bomber"), // 4 Cards.FromName("Stonetusk Boar"), // 5 Cards.FromName("Magma Rager"), // 6 Cards.FromName("War Golem"), // 7 Cards.FromName("Reckless Rocketeer"), // 8 Cards.FromName("Wolfrider"), // 9 Cards.FromName("Sen'jin Shieldmasta"), // 10 Cards.FromName("Voodoo Doctor"), // 11 Cards.FromName("River Crocolisk"), // 12 Cards.FromName("Oasis Snapjaw"), // 13 Cards.FromName("Novice Engineer"), // 14 Cards.FromName("Core Hound"), // 15 Cards.FromName("Booty Bay Bodyguard"), // 16 Cards.FromName("Ogre Magi"), // 17 Cards.FromName("Chillwind Yeti"), // 18 Cards.FromName("Acidic Swamp Ooze"), // 19 Cards.FromName("Ironfur Grizzly"), // 20 Cards.FromName("Bluegill Warrior"), // 21 Cards.FromName("Murloc Tidehunter"), // 22 Cards.FromName("Frostwolf Grunt"), // 23 Cards.FromName("Ironforge Rifleman"), // 24 Cards.FromName("Kobold Geomancer"), // 25 Cards.FromName("Razorfen Hunter"), // 26 Cards.FromName("Gnomish Inventor"), // 27 Cards.FromName("Stormwind Knight"), // 28 Cards.FromName("Gurubashi Berserker"), // 29 Cards.FromName("Elven Archer"), // 30 }, FillDecks = false, Shuffle = false, Splitting = true }); game.StartGame(); game.Process(EndTurnTask.Any(game.CurrentPlayer)); game.Process(PlayCardTask.Spell(game.CurrentPlayer, game.CurrentPlayer.HandZone[4])); // Coin game.Process(PlayCardTask.Minion(game.CurrentPlayer, game.CurrentPlayer.HandZone[0])); // Loot Hoarder game.Process(EndTurnTask.Any(game.CurrentPlayer)); game.Process(PlayCardTask.Minion(game.CurrentPlayer, game.CurrentPlayer.HandZone[0])); // Loot Hoarder game.Process(EndTurnTask.Any(game.CurrentPlayer)); game.Process(PlayCardTask.Minion(game.CurrentPlayer, game.CurrentPlayer.HandZone[1])); // Huge Toad game.Process(EndTurnTask.Any(game.CurrentPlayer)); game.Process(PlayCardTask.Minion(game.CurrentPlayer, game.CurrentPlayer.HandZone[0])); // Loot Hoarder game.Process(EndTurnTask.Any(game.CurrentPlayer)); game.Process(PlayCardTask.Minion(game.CurrentPlayer, game.CurrentPlayer.HandZone[1])); // Mad Bomber //game.Process(PlayCardTask.Minion(game.CurrentPlayer, game.CurrentPlayer.Hand[2])); goOnFlag = false; } ShowLog(game, LogLevel.VERBOSE); }
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> /// Ends the current player's turn. /// </summary> public static void EndTurn(this Game game) { game.Process(EndTurnTask.Any(game.CurrentPlayer)); }
public void BasicHealthAuraTest1() { var game = new Game(new GameConfig { StartPlayer = 1, Player1HeroClass = CardClass.PALADIN, Player2HeroClass = CardClass.MAGE, FillDecks = true, FillDecksPredictably = true }); game.Player1.BaseMana = 10; game.Player2.BaseMana = 10; game.StartGame(); var minion1 = (Minion)Generic.DrawCard(game.CurrentPlayer, Cards.FromName("Stormwind Champion")); var minion2 = (Minion)Generic.DrawCard(game.CurrentPlayer, Cards.FromName("Stormwind Champion")); var minion3 = (Minion)Generic.DrawCard(game.CurrentPlayer, Cards.FromName("Shattered Sun Cleric")); game.Process(PlayCardTask.Minion(game.CurrentPlayer, minion1)); // 6/6 game.CurrentPlayer.UsedMana = 0; game.Process(PlayCardTask.Minion(game.CurrentPlayer, minion2)); // 7/7 game.CurrentPlayer.UsedMana = 0; game.Process(PlayCardTask.MinionTarget(game.CurrentPlayer, minion3, minion2)); game.CurrentPlayer.UsedMana = 0; Assert.Equal(7, minion1.AttackDamage); Assert.Equal(7, minion1.Health); Assert.Equal(8, minion2.AttackDamage); Assert.Equal(8, minion2.Health); Assert.Equal(5, minion3.AttackDamage); Assert.Equal(4, minion3.Health); game.Process(EndTurnTask.Any(game.CurrentPlayer)); // (7/7), (8/8), (5/4) IPlayable spell1 = Generic.DrawCard(game.CurrentPlayer, Cards.FromName("Flamestrike")); game.Process(PlayCardTask.Spell(game.CurrentPlayer, spell1)); // (7/3), (8/4) game.CurrentPlayer.UsedMana = 0; IPlayable spell2 = Generic.DrawCard(game.CurrentPlayer, Cards.FromName("Arcane Explosion")); game.Process(PlayCardTask.Spell(game.CurrentPlayer, spell2)); IPlayable spell3 = Generic.DrawCard(game.CurrentPlayer, Cards.FromName("Arcane Explosion")); game.Process(PlayCardTask.Spell(game.CurrentPlayer, spell3)); Assert.Equal(2, ((ICharacter)minion2).Health); // (7/1), (8/2) IPlayable spell4 = Generic.DrawCard(game.CurrentPlayer, Cards.FromName("Arcane Explosion")); game.Process(PlayCardTask.Spell(game.CurrentPlayer, spell4)); Assert.Equal(1, ((ICharacter)minion2).Health); // (7/1) Assert.Equal(Zone.PLAY, ((ICharacter)minion2).Zone.Type); }