private float Simulation(Node nodeToSimulate, POGame poGame) { float result = -1; int simulationSteps = 0; PlayerTask task = null; List <PlayerTask> taskToSimulate = new List <PlayerTask>(); if (poGame == null) { return(0.5f); } if (nodeToSimulate.task.PlayerTaskType == PlayerTaskType.END_TURN) { return(Estimator.estimateFromState(ESTIMATION_MODE, poGame)); } while (poGame.getGame().State != SabberStoneCore.Enums.State.COMPLETE) { task = SimulationPolicies.selectSimulationPolicy(SIMULATION_POLICY, poGame, Rnd, greedyAgent, CHILDREN_CONSIDERED_SIMULATING); taskToSimulate.Add(task); if (task.PlayerTaskType != PlayerTaskType.END_TURN) { poGame = poGame.Simulate(taskToSimulate)[taskToSimulate[0]]; } taskToSimulate.Clear(); if (poGame == null) { return(0.5f); } if (task.PlayerTaskType == PlayerTaskType.END_TURN) { return(Estimator.estimateFromState(ESTIMATION_MODE, poGame)); } simulationSteps++; } if (poGame.CurrentPlayer.PlayState == SabberStoneCore.Enums.PlayState.CONCEDED || poGame.CurrentPlayer.PlayState == SabberStoneCore.Enums.PlayState.LOST) { result = 0; } else if (poGame.CurrentPlayer.PlayState == SabberStoneCore.Enums.PlayState.WON) { result = 1; } return(result); }
private PlayerTask HandleMulligan(POGame poGame) { Controller me = poGame.CurrentPlayer; if (me.MulliganState == Mulligan.INPUT) { List <IPlayable> cards = me.Choice.Choices.Select(p => poGame.getGame().IdEntityDic[p]).ToList(); return(ChooseTask.Mulligan(me, cards.Where(x => x.Card.Cost <= 3).Select(x => x.Id).ToList())); } return(null); }
private float Simulate(Node nodeToSimulate, POGame poGame) { float result = -1; int simulationSteps = 0; PlayerTask task = null; if (poGame == null) { return(0.5f); } List <PlayerTask> taskToSimulate = new List <PlayerTask>(1); taskToSimulate.Add(null); while (poGame.getGame().State != SabberStoneCore.Enums.State.COMPLETE) { task = Greedy(poGame); taskToSimulate[0] = task; if (task.PlayerTaskType != PlayerTaskType.END_TURN) { poGame = poGame.Simulate(taskToSimulate)[taskToSimulate[0]]; } if (poGame == null) { return(0.5f); } if (task.PlayerTaskType == PlayerTaskType.END_TURN) { return(ScoreToValue(Score(poGame))); } simulationSteps++; } if (poGame.CurrentPlayer.PlayState == SabberStoneCore.Enums.PlayState.CONCEDED || poGame.CurrentPlayer.PlayState == SabberStoneCore.Enums.PlayState.LOST) { result = 0; } else if (poGame.CurrentPlayer.PlayState == SabberStoneCore.Enums.PlayState.WON) { result = 1; } return(result); }
public double Evaluate(POGame state) { if (SOCKET_EVAL && NNSocket != null) { return((double)SocketEvaluate(state.getGame())); } if (!state.CurrentPlayer.Name.Equals(controller.Name)) { Console.WriteLine("ERROR: Evaluating opponent's state!"); return(new DogZooLockScore { Controller = state.CurrentOpponent }.Evaluate()); } return(new DogZooLockScore { Controller = state.CurrentPlayer }.Evaluate()); }
public override PlayerTask GetMove(POGame poGame) { Controller player = poGame.CurrentPlayer; IEnumerable <KeyValuePair <PlayerTask, POGame> > validOpts = poGame.Simulate(player.Options()).Where(x => x.Value != null); int optcount = validOpts.Count(); int maxMilliseconds = 25000; // Math.Min(Math.Max(optcount * 2000, 8000), 20000); // Implement a simple Mulligan Rule if (player.MulliganState == Mulligan.INPUT) { List <int> mulligan = new MyScore().MulliganRule().Invoke(player.Choice.Choices.Select(p => poGame.getGame().IdEntityDic[p]).ToList()); return(ChooseTask.Mulligan(player, mulligan)); } PlayerTask returnTask = validOpts.Any() ? GetMoveMCTS(poGame.getCopy(), maxMilliseconds) : player.Options().First(x => x.PlayerTaskType == PlayerTaskType.END_TURN); if (returnTask == null) { returnTask = player.Options().First(x => x.PlayerTaskType == PlayerTaskType.END_TURN); } return(returnTask); }
public override PlayerTask GetMove(POGame game) { var player = game.CurrentPlayer; int pid = player.PlayerId; if (player.MulliganState == Mulligan.INPUT) { List <int> mulligan = new KnobiScore().MulliganRule().Invoke(player.Choice.Choices.Select(p => game.getGame().IdEntityDic[p]).ToList()); return(ChooseTask.Mulligan(player, mulligan)); } // simulation stage 1 var validOpts = game.Simulate(player.Options()).Where(x => x.Value != null); if (validOpts.Any()) { PlayerTask task = validOpts.First().Key; // initialize best score as current score int bestScore = Score(game, pid); // simulate the (maxSimPerStep) best solutions int i1 = 0; foreach (var opt in validOpts.OrderBy(x => - Score(x.Value, pid))) { if (i1 > maxSimPerStep || opt.Key.PlayerTaskType == PlayerTaskType.END_TURN) { continue; } ++i1; int optScore = Score(opt.Value, pid); // return action if it leads to win if (optScore == Int32.MaxValue) { return(opt.Key); } // skip action if it leads to defete if (optScore == Int32.MinValue) { continue; } // start simulation stage 2 var validOpts2 = opt.Value.Simulate(opt.Value.CurrentPlayer.Options()).Where(x => x.Value != null); int i2 = 0; foreach (var opt2 in validOpts2.OrderBy(x => - Score(x.Value, pid))) { if (i2 > maxSimPerStep || opt2.Key.PlayerTaskType == PlayerTaskType.END_TURN) { continue; } ++i2; optScore = Math.Max(optScore, Score(opt2.Value, pid)); if (optScore == Int32.MaxValue) { return(opt.Key); } if (optScore == Int32.MinValue) { continue; } //start simulation stage 3 if (useThirdStep) { var validOpts3 = opt.Value.Simulate(opt.Value.CurrentPlayer.Options()).Where(x => x.Value != null); foreach (var opt3 in validOpts3.OrderBy(x => - Score(x.Value, pid))) { if (opt3.Key.PlayerTaskType == PlayerTaskType.END_TURN) { continue; } optScore = Math.Max(optScore, Score(opt3.Value, pid)); if (optScore == Int32.MaxValue) { return(opt.Key); } if (optScore == Int32.MinValue) { continue; } } } } // update desicion, if it is better if (optScore > bestScore) { bestScore = optScore; task = opt.Key; } } return(task); } // if there are no possible solutions, end the turn return(player.Options().First(x => x.PlayerTaskType == PlayerTaskType.END_TURN)); }
public override PlayerTask GetMove(POGame poGame) { List <int> values = new List <int>(); List <PlayerTask> turnList = new List <PlayerTask>(); PlayerTask bestOption = null; int bestValue = int.MinValue; JadeScore jade = new JadeScore(); Controller control = poGame.CurrentPlayer; Dictionary <PlayerTask, POGame> simulated = poGame.Simulate(control.Options()); if (control.MulliganState == Mulligan.INPUT) { List <int> mulligan = jade.MulliganRule().Invoke(control.Choice.Choices.Select(p => poGame.getGame().IdEntityDic[p]).ToList()); return(ChooseTask.Mulligan(control, mulligan)); } if (control.Options().Count == 1) { return(control.Options()[0]); } oppPlayedCards = poGame.CurrentOpponent.PlayHistory; foreach (PlayHistoryEntry h in oppPlayedCards) { if (h.SourceCard.Name == "Flamestrike") { countFlamestrike = 1; } } foreach (PlayerTask k in simulated.Keys) { if (k.PlayerTaskType == PlayerTaskType.END_TURN) { continue; } if (poGame.CurrentPlayer.BoardZone.Count >= 4 && k.PlayerTaskType == PlayerTaskType.PLAY_CARD && k.Source.Card.Type == CardType.MINION) { continue; } if (poGame.CurrentOpponent.HeroClass == CardClass.MAGE && poGame.CurrentOpponent.BaseMana >= 7 && countFlamestrike == 0 && k.PlayerTaskType == PlayerTaskType.PLAY_CARD && k.Source.Card.Type == CardType.MINION && k.Source.Card[GameTag.HEALTH] <= 4 && poGame.CurrentPlayer.BoardZone.Count >= 2) { continue; } //controller of simulated option control = simulated.First(x => x.Key == k).Value?.CurrentPlayer; if (control == null) { continue; } //set controller on rating function //controlScore.Controller = control; jade.Controller = control; //rate current option var currentValue = jade.BetterRate(_rewardOppNoBoard, _rewardOppNoHand, _rewardBoardDiff, _rewardTauntDiff, _rewardHeroDiff, _rewardHandDiff, _rewardDeckDiff, _rewardMinAttDiff, _rewardMinHealthDiff, _rewardHeroAttDiff, _rewardHandCost); if (bestValue < currentValue) { bestValue = currentValue; bestOption = k; } } //debug(turnList, values, bestOption, bestValue, poGame); return(bestOption ?? (bestOption = poGame.CurrentPlayer.Options().Find(x => x.PlayerTaskType == PlayerTaskType.END_TURN))); }
public override PlayerTask GetMove(POGame poGame) { var player = poGame.CurrentPlayer; // During Mulligan: select Random cards if (player.MulliganState == Mulligan.INPUT) { List <int> mulligan = RandomMulliganRule().Invoke(player.Choice.Choices.Select(p => poGame.getGame().IdEntityDic[p]).ToList()); return(ChooseTask.Mulligan(player, mulligan)); } // During Gameplay: select a random action List <PlayerTask> options = poGame.CurrentPlayer.Options(); return(options[Rnd.Next(options.Count)]); }
public override PlayerTask GetMove(POGame poGame) { outputOptional("-----------new get Move-------------"); initialDebug(poGame); debugBoardZone(poGame); Controller player = poGame.CurrentPlayer; List <double> scores = new List <double>(); outputMyCards(poGame); if (player.MulliganState == Mulligan.INPUT) { outputOptional("\ntime for mulligan"); List <int> mulligan = MulliganRule().Invoke(player.Choice.Choices.Select(p => poGame.getGame().IdEntityDic[p]).ToList()); outputOptional("mulligan options:"); for (int i = 0; i < mulligan.Count; i++) { outputOptional(mulligan[i].ToString()); } outputOptional(ChooseTask.Mulligan(player, mulligan).ToString()); //outputOptional("muligan choices: " + player.Choice.Choices.ToString()); return(ChooseTask.Mulligan(player, mulligan)); } List <PlayerTask> options = poGame.CurrentPlayer.Options(); debugOptions(options, player); if (options.Count == 1) { if (options[0].PlayerTaskType == PlayerTaskType.END_TURN) { outputOptional("ending turn because only one end turn option available"); outputOptional("########### New Round ###########"); currentTurn += 1; return(options[0]); } else { outputPriorityHigh("[Error]: only one option left but its not ending a turn"); return(options[0]); } } var simulated = poGame.Simulate(options); foreach (var s in simulated) { // s.Value is the POGame of that simulated move scores.Add(Score(s.Key, s.Value)); } //debugScoringOptions(simulated, scores); debugSimScoringOptions(simulated, scores); int highestScoringIndex = HighestValue(scores); if (highestScoringIndex == 0 && player.RemainingMana > 1) { numGamesEndturnManaMoreThanTwo++; numGamesEndturnManaMoreThanTwoTotal++; outputPriorityHigh("m8 premature end of turn: Mana:" + player.RemainingMana.ToString() + "|" + options[0].ToString()); } outputOptional("choosing this task: " + options[highestScoringIndex].ToString() + " at " + highestScoringIndex); return(options[highestScoringIndex]); }
public override PlayerTask GetMove(POGame game) { var player = game.CurrentPlayer; // Implement a simple Mulligan Rule if (player.MulliganState == Mulligan.INPUT) { List <int> mulligan = new WeightedScore().MulliganRule().Invoke(player.Choice.Choices.Select(p => game.getGame().IdEntityDic[p]).ToList()); return(ChooseTask.Mulligan(player, mulligan)); } //Lookhead n steps and choose the best scoring <PlayerTask> and each depth -> branch ->score->until depth //(DFS search) var validOpts = game.Simulate(player.Options()).Where(x => x.Value != null); var voptcount = validOpts.Count(); if (validOpts.Any()) { var depth = voptcount > 5 ? (voptcount > 25 ? 1: 2) : 3; var scored = validOpts.Select(x => Simulate(x, player.PlayerId, depth)); // Array.ForEach(scored.Select(x=>x.Item1).ToArray(),Console.Write); // Console.Write($"\r{scored.Count()} "); return(scored.OrderBy(x => x.Value).Last().Key); } else { return(player.Options().First(x => x.PlayerTaskType == PlayerTaskType.END_TURN)); } }
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 override PlayerTask GetMove(POGame game) { Controller player = game.CurrentPlayer; if (h_score == -1) { determineScore(player); } // Implement a simple Mulligan Rule if (player.MulliganState == Mulligan.INPUT) { List <int> mulligan = new HarderMidRangeScore().MulliganRule().Invoke(player.Choice.Choices.Select(p => game.getGame().IdEntityDic[p]).ToList()); return(ChooseTask.Mulligan(player, mulligan)); } finishedBuildingTree = false; if (!finishedBuildingTree) { actionsToTake = new List <PlayerTask>(); } if (actionsToTake.Count != 0) { PlayerTask action = DequeueTask(); finishedBuildingTree = actionsToTake.Count != 0; /*if (!finishedBuildingTree) { * Console.WriteLine("My health: " + poGame.CurrentPlayer.Hero.Health); * Console.WriteLine("Opponent health: " + poGame.CurrentOpponent.Hero.Health); * Console.WriteLine("\n\n\n"); * } * Console.WriteLine(String.Format("Action: {0}", action));*/ return(action); } List <MinMaxAgentState> leaves = new List <MinMaxAgentState>(); List <MinMaxAgentState> parentStates = new List <MinMaxAgentState>() { new MinMaxAgentState(game) }; // while we have moves to play // int generation = 0; while (true) { // split currentLevel into leaves "partitioned[false]" // and non-leaves "partitioned[true]" ILookup <bool, MinMaxAgentState> partitioned = parentStates.ToLookup( currentLevelNonLeaf => currentLevelNonLeaf.OnlyActionIsEndTurn || currentLevelNonLeaf.ActionsToReachState.Count >= 6 ); IEnumerable <MinMaxAgentState> parentLeaves = partitioned[true]; List <MinMaxAgentState> nonParentLeaves = partitioned[false].ToList(); leaves.AddRange(parentLeaves.ToList()); if (nonParentLeaves.Count == 0) { break; } //Console.WriteLine(String.Format("leaves.Count = {0}", leaves.Count)); //Console.WriteLine(String.Format("haveMoreActions.Count = {0}\n", haveMoreActions.Count)); //if (haveMoreActions.Count == 0) { // break; //} List <MinMaxAgentState> childrenStates = new List <MinMaxAgentState>(); //Console.WriteLine(String.Format("========== Actions My Bot Can Take ==========")); //Console.WriteLine(String.Format("Iteration #{0}\n\n", ++generation)); foreach (MinMaxAgentState hasMoreAction in nonParentLeaves) { Dictionary <PlayerTask, POGame> mapping = hasMoreAction.State.Simulate( hasMoreAction.AvailableActions.ToList() );//.Where( x => x.Value != null ); foreach (KeyValuePair <PlayerTask, POGame> actionState in mapping) { if (actionState.Value != null) { /*if (actionState.Key.FullPrint().Contains("Player1")) { * continue; * } * Console.WriteLine(actionState.Key.FullPrint());*/ childrenStates.Add(new MinMaxAgentState(hasMoreAction, actionState)); } } } // Get the top N childrenStates var childrenStatesWithScore = childrenStates.Zip(childrenStates.Select( childState => Score(childState.State, childState.State.CurrentPlayer.PlayerId) ), (state, score) => new Tuple <MinMaxAgentState, double>(state, score)).ToList(); childrenStatesWithScore.Sort((lhs, rhs) => rhs.Item2.CompareTo(lhs.Item2)); parentStates = childrenStatesWithScore.Take(MAX_CHILD_COUNT).Select( stateScore => stateScore.Item1 ).ToList(); } // No moves possible i.e. no leaves var finalCandidates = leaves.ToList(); if (finalCandidates.Count == 0) { actionsToTake.Add(EndTurnTask.Any(parentStates[0].State.CurrentPlayer.Controller)); return(DequeueTask()); } // Get the very best MinMaxAgentState bestState = MaxByKey(finalCandidates, (lhs, rhs) => { return(Score(lhs.State, lhs.State.CurrentPlayer.Id) < Score(rhs.State, rhs.State.CurrentPlayer.Id) ? rhs : lhs); }); actionsToTake = bestState.ActionsToReachState; if (actionsToTake.Count == 0 || actionsToTake[actionsToTake.Count - 1].PlayerTaskType != PlayerTaskType.END_TURN) { actionsToTake.Add(EndTurnTask.Any(bestState.State.CurrentPlayer.Controller)); } finishedBuildingTree = true; // Console.WriteLine(String.Format("Turn Counter @ {0}", ++turnCounter)); return(DequeueTask()); }
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]); } }
public void FinalizeGame(POGame game) { bool won; if (_me.PlayerId == 1) { won = game.getGame().Player1.PlayState == PlayState.WON; } else { won = game.getGame().Player2.PlayState == PlayState.WON; } bool tied = game.CurrentPlayer.PlayState == PlayState.TIED; bool maxTurnsReached = game.getGame().State == State.RUNNING; float discount = 0.98f; float alpha = 0.00001f; //Console.WriteLine("Gamestate: " + game.getGame().State); //Console.WriteLine("I am player " + _me.PlayerId); //Console.WriteLine("State of Player1:" + game.getGame().Player1.PlayState); //Console.WriteLine("State of Player2:" + game.getGame().Player2.PlayState); //Console.WriteLine("Won: " + won); //Console.WriteLine("Tied: " + tied); //Console.WriteLine("Max turns reached: " + maxTurnsReached); double reward = won ? 10 : -10; reward = tied ? 0 : reward; reward = maxTurnsReached ? -5 : reward; //Console.WriteLine(reward); var weights = new List <double>(MagicNumberScore.Factors); double total_squared_error = 0; //Console.WriteLine(_scores.Count); for (int i = 1; i < _scores.Count; i++) { var d_return = reward * Math.Pow(discount, (_scores.Count() - i - 1)); double error = d_return - _scores[i]; //Console.WriteLine("Error in turn " + i + ": " + Math.Pow(error, 2)); total_squared_error += Math.Pow(error, 2); var fl = new List <double>(_features[i]).Zip(new List <double>(_features[i - 1]), (a, b) => (a, b)); weights = weights.Zip(fl, (w, f) => (w + alpha * error * (f.b - f.a))).ToList(); } //Console.WriteLine("New Weights:"); for (int i = 0; i < weights.Count(); i++) { Console.Write($"{i}: {weights[i]}|"); } MagicNumberScore.Factors = weights.ToArray(); //Console.WriteLine("Normailized Weights:"); for (int i = 0; i < MagicNumberScore.Factors.Count(); i++) { Console.Write($"{i}: {MagicNumberScore.Factors[i]}|"); } //Console.WriteLine("-------------"); //Console.WriteLine("Total squared error this game: " + total_squared_error); }
public override PlayerTask GetMove(POGame poGame) { //Console.WriteLine("NEW TURN:"); Controller player = poGame.CurrentPlayer; if (player.HeroClass == CardClass.WARRIOR) { hWarrior = 1; hMage = 0; hShaman = 0; } else if (player.HeroClass == CardClass.MAGE) { hWarrior = 0; hMage = 1; hShaman = 0; } else { hWarrior = 0; hMage = 0; hShaman = 1; } if (player.MulliganState == Mulligan.INPUT) { List <int> mulligan = new MyScore().GetMulliganRule().Invoke(player.Choice.Choices.Select(p => poGame.getGame().IdEntityDic[p]).ToList()); } // Get all simulation results for simulations that didn't fail IEnumerable <KeyValuePair <PlayerTask, POGame> > validOpts = poGame.Simulate(player.Options()).Where(x => x.Value != null); if (validOpts.Any()) { var move = new KeyValuePair <PlayerTask, int>(validOpts.First().Key, Score(poGame, player.PlayerId)); var nScore = new KeyValuePair <PlayerTask, int>(validOpts.First().Key, Score(poGame, player.PlayerId)); foreach (KeyValuePair <PlayerTask, POGame> playerTask in validOpts) { if (validOpts.Count() >= 8) { if (validOpts.Count() >= 24) { nScore = nextScore(playerTask, player.PlayerId, 1); if (nScore.Value > move.Value) { move = nScore; } } else { nScore = nextScore(playerTask, player.PlayerId, 2); if (nScore.Value > move.Value) { move = nScore; } } } else { nScore = nextScore(playerTask, player.PlayerId, 3); if (nScore.Value > move.Value) { move = nScore; } } } //Console.WriteLine(poGame.PartialPrint()); //Console.WriteLine("......................"); //Console.WriteLine(move.Key +" mit: "+ move.Value); //Console.WriteLine("-----------------------"); return(move.Key); } else { return(player.Options().First(x => x.PlayerTaskType == PlayerTaskType.END_TURN)); } }
public override PlayerTask GetMove(POGame game) { //StopWatch.StartWithReset(); int threadCount = 4; var player = game.CurrentPlayer; var opponent = game.CurrentOpponent; var validOpts = game.Simulate(player.Options()).Where(x => x.Value != null); var optsCount = validOpts.Count(); var history = opponent.PlayHistory; // Implement a simple Mulligan Rule if (player.MulliganState == Mulligan.INPUT) { List <int> mulligan = new AggroScore().MulliganRule().Invoke(player.Choice.Choices.Select(p => game.getGame().IdEntityDic[p]).ToList()); return(ChooseTask.Mulligan(player, mulligan)); } countProbabilities(); MCTS mcts = new MCTS(game, DecksDict, ProbabilitiesDict, TurnDepth, TimeBudget, Selection, StateRate, ExplorationConstant); PlayerTask result = mcts.Search(); //StopWatch.StopWithMessage(String.Format("Compute {0} options in {1} ms", optcount, StopWatch.ElapsedMilliseconds)); //Console.WriteLine("Final task: " + result); return(result); void countProbabilities() { /* ----------- Counting probabilities ------------ */ foreach (KeyValuePair <string, List <Card> > deck in DecksDict) { int similarCount = 0; var playedCards = history.Select(h => h.SourceCard).ToList(); var deckCards = deck.Value; var deckCardsDistinct = deckCards.Distinct().ToList(); playedCards .ForEach(playedCard => { deckCardsDistinct.ForEach(deckCard => { if (playedCard.Name == deckCard.Name) { similarCount++; } }); }); double probability = Math.Round((double)similarCount / deckCards.Count(), 2); ProbabilitiesDict[deck.Key] = probability; //if (probability > 0) Console.WriteLine(deck.Key + " has probability of " + ProbabilitiesDict[deck.Key] * 100 + "%"); } } }
public override PlayerTask GetMove(POGame poGame) { var player = poGame.CurrentPlayer; // Implement a simple Mulligan Rule if (player.MulliganState == Mulligan.INPUT) { List <int> mulligan = new CustomScore().MulliganRule().Invoke(player.Choice.Choices.Select(p => poGame.getGame().IdEntityDic[p]).ToList()); return(ChooseTask.Mulligan(player, mulligan)); } if (poGame.CurrentPlayer.Options().Count == 1) { return(poGame.CurrentPlayer.Options()[0]); } POGame initialState = poGame.getCopy(); Node root = new Node(); Node selectedNode; Node nodeToSimulate; float scoreOfSimulation; int iterations = 0; InitializeRoot(root, initialState); Stopwatch stopwatch = new Stopwatch(); stopwatch.Start(); while (stopwatch.ElapsedMilliseconds <= MAX_TIME) { poGame = initialState; selectedNode = Selection(root, iterations, ref poGame); nodeToSimulate = Expansion(selectedNode, ref poGame); for (int i = 0; i < NUM_SIMULATIONS; i++) { scoreOfSimulation = Simulation(nodeToSimulate, poGame); Backpropagation(nodeToSimulate, scoreOfSimulation); iterations++; } } stopwatch.Stop(); return(SelectAction.selectTask(SELECTION_ACTION_METHOD, root, iterations, EXPLORE_CONSTANT)); }
public override PlayerTask GetMove(POGame poGame) { _player = poGame.CurrentPlayer; if (_player.MulliganState == Mulligan.INPUT) { List <int> mulligan = new DefaultScore().MulliganRule().Invoke(_player.Choice.Choices.Select(p => poGame.getGame().IdEntityDic[p]).ToList()); return(ChooseTask.Mulligan(_player, mulligan)); } Dictionary <KeyValuePair <PlayerTask, POGame>, int> ScoreDict = new Dictionary <KeyValuePair <PlayerTask, POGame>, int>(); Stopwatch stopwatch = new Stopwatch(); var simulation = poGame.Simulate(_player.Options()).Where(x => x.Value != null); simulation = simulation.OrderBy(x => Score(x.Value, _player.PlayerId)); stopwatch.Start(); foreach (var task in simulation) { if (stopwatch.ElapsedMilliseconds > 25000) { break; } if (task.Key.PlayerTaskType == PlayerTaskType.END_TURN) { ScoreDict.Add(task, Score(task.Value, _player.PlayerId)); continue; } POGame gamecopy = task.Value.getCopy(); var options = gamecopy.CurrentPlayer.Options(); var simulationv2 = gamecopy.Simulate(options).Where(x => x.Value != null); simulationv2 = simulationv2.OrderBy(x => Score(x.Value, _player.PlayerId)); Dictionary <KeyValuePair <PlayerTask, POGame>, int> ScoreDict2 = new Dictionary <KeyValuePair <PlayerTask, POGame>, int>(); foreach (var task2 in simulationv2) { if (stopwatch.ElapsedMilliseconds > 25000) { break; } POGame gamecopy2 = task2.Value.getCopy(); var options2 = gamecopy2.CurrentPlayer.Options(); if (task2.Key.PlayerTaskType == PlayerTaskType.END_TURN || options2.Count > 20) { ScoreDict2.Add(task2, Score(task2.Value, _player.PlayerId)); continue; } var simulationv3 = gamecopy2.Simulate(options2).Where(x => x.Value != null); simulationv3 = simulationv3.OrderBy(x => Score(x.Value, _player.PlayerId)); //evaluate the best score out of the third simulation and add it in scoredict 2 ScoreDict2.Add(task2, Score(simulationv3.OrderBy(x => Score(x.Value, _player.PlayerId)).Last().Value, _player.PlayerId)); } ScoreDict.Add(task, ScoreDict2.OrderBy(x => x.Value).Last().Value); } //if(stopwatch.ElapsedMilliseconds>25000) // Console.WriteLine(stopwatch.ElapsedMilliseconds); return(simulation.Any() ? ScoreDict.OrderBy(x => x.Value).Last().Key.Key : _player.Options().First(x => x.PlayerTaskType == PlayerTaskType.END_TURN)); }
public override PlayerTask GetMove(POGame poGame) { var player = poGame.CurrentPlayer; // Implement a simple Mulligan Rule if (player.MulliganState == Mulligan.INPUT) { List <int> mulligan = new CustomMidrangeScoreHempel().MulliganRule().Invoke(player.Choice.Choices.Select(p => poGame.getGame().IdEntityDic[p]).ToList()); switch (poGame.CurrentPlayer.HeroClass) { case CardClass.SHAMAN: goto case CardClass.HUNTER; case CardClass.PALADIN: goto case CardClass.HUNTER; case CardClass.DRUID: goto case CardClass.HUNTER; case CardClass.ROGUE: goto case CardClass.HUNTER; case CardClass.HUNTER: mulligan = new CustomMidrangeScoreHempel().MulliganRule().Invoke(player.Choice.Choices.Select(p => poGame.getGame().IdEntityDic[p]).ToList()); break; case CardClass.WARLOCK: goto case CardClass.WARRIOR; case CardClass.WARRIOR: mulligan = new CustomAggroScoreHempel().MulliganRule().Invoke(player.Choice.Choices.Select(p => poGame.getGame().IdEntityDic[p]).ToList()); break; case CardClass.PRIEST: goto case CardClass.MAGE; case CardClass.MAGE: mulligan = new CustomControlScoreHempel().MulliganRule().Invoke(player.Choice.Choices.Select(p => poGame.getGame().IdEntityDic[p]).ToList()); break; default: mulligan = new CustomMidrangeScoreHempel().MulliganRule().Invoke(player.Choice.Choices.Select(p => poGame.getGame().IdEntityDic[p]).ToList()); break; } return(ChooseTask.Mulligan(player, mulligan)); } // Get all simulation results for simulations that didn't fail var validOpts = poGame.Simulate(player.Options()).Where(x => x.Value != null); // List of best pairs var ActionScore = new List <KeyValuePair <PlayerTask, int> >(); foreach (KeyValuePair <PlayerTask, POGame> pair in validOpts) { var optionsDeep1 = pair.Value.CurrentPlayer.Options(); //get substate options var bestDeepActionState = new KeyValuePair <PlayerTask, POGame>(); if (optionsDeep1.Any() && pair.Key.PlayerTaskType != PlayerTaskType.END_TURN) { var validDeep1Options = pair.Value.Simulate(optionsDeep1).Where(x => x.Value != null); //get valid substate options if (validDeep1Options.Any()) { bestDeepActionState = validDeep1Options.OrderBy(x => Score(x.Value, player.PlayerId)).Last(); ActionScore.Add(new KeyValuePair <PlayerTask, int>(pair.Key, (int)(0.2 * (double)Score(pair.Value, player.PlayerId) + 0.8 * (double)Score(bestDeepActionState.Value, player.PlayerId)))); } else { ActionScore.Add(new KeyValuePair <PlayerTask, int>(pair.Key, Score(pair.Value, player.PlayerId))); } } else { // collect best tasks per done task ActionScore.Add(new KeyValuePair <PlayerTask, int>(pair.Key, Score(pair.Value, player.PlayerId))); } } // return the action with the best combination of current task and next task return(validOpts.Any() ? ActionScore.OrderBy(x => x.Value).Last().Key : player.Options().First(x => x.PlayerTaskType == PlayerTaskType.END_TURN)); }
public override PlayerTask GetMove(POGame game) { var player = game.CurrentPlayer; // Implement a simple Mulligan Rule if (player.MulliganState == Mulligan.INPUT) { List <int> mulligan = new CustomScore().MulliganRule().Invoke(player.Choice.Choices.Select(p => game.getGame().IdEntityDic[p]).ToList()); return(ChooseTask.Mulligan(player, mulligan)); } var opponent = game.CurrentOpponent; var options = player.Options(); var validOpts = game.Simulate(options).Where(x => x.Value != null); var optcount = validOpts.Count(); #if DEBUG /* * var score_res = validOpts.Select(x => score(x, player.PlayerId, (optcount >= 5) ? ((optcount >= 25) ? 1 : 2) : 3)).OrderBy(x => x.Value); * * Console.WriteLine("Round Nr:" + Convert.ToString(game.Turn)); * Console.WriteLine("HeroHP: " + Convert.ToString(player.Hero.Health) + "\tOppHP: " + Convert.ToString(game.CurrentOpponent.Hero.Health)); * Console.WriteLine("HeroMinionHP: " + Convert.ToString(player.BoardZone.Sum(p => p.Health)) + "\tOppMinionHP: " + Convert.ToString(game.CurrentOpponent.BoardZone.Sum(p => p.Health))); * Console.WriteLine("HeroMinionAtk: " + Convert.ToString(player.BoardZone.Sum(p => p.AttackDamage)) + "\tOppMinionAtk: " + Convert.ToString(game.CurrentOpponent.BoardZone.Sum(p => p.AttackDamage))); * Console.WriteLine("HeroNbMinions: " + Convert.ToString(player.BoardZone.Count) + "\tOppMinionNB: " + Convert.ToString(game.CurrentOpponent.BoardZone.Count)); * * * foreach (var tmp_score in score_res) * { * * Console.WriteLine(Convert.ToString(tmp_score.Key) + Convert.ToString(tmp_score.Value)); * } * Console.WriteLine("-------------------------------------------------------"); * //PrintLog(game, score_res); */ #endif /* * if (player.Hero.Health < DEFENSE_HEALTH_THRESHOLD * player.Hero.BaseHealth) * RuntimeScaling[0] += 0.1; * * if (opponent.Hero.Health < DEFENSE_HEALTH_THRESHOLD * opponent.Hero.Health) * RuntimeScaling[1] += 0.1; */ var opt1 = options.Where(x => x.HasSource && x.Source.Card.Name == "Reno Jackson"); //if (opt1.Count() > 0 && (player.Hero.Health - opponent.Hero.AttackDamage - opponent.BoardZone.Sum(p => p.AttackDamage) <= 3 || player.Hero.Health<10)) //if (opt1.Count() > 0 && (player.Hero.Health - opponent.Hero.AttackDamage - opponent.BoardZone.Sum(p => p.AttackDamage) <= 6 )) if (opt1.Count() > 0 && (player.Hero.Health - opponent.Hero.AttackDamage - opponent.BoardZone.Sum(p => p.AttackDamage) <= 3 || player.Hero.Health < 10)) { var tmp_game = game.getCopy(); //Reno Jackson has 6 mana int mana = (tmp_game.CurrentPlayer.RemainingMana - 6) > 0 ? (tmp_game.CurrentPlayer.RemainingMana - 6) : 0; //Console.WriteLine("mana " + Convert.ToString(tmp_game.CurrentPlayer.BaseMana)); var validOptsLoc = tmp_game.Simulate(options).Where(x => x.Value != null); var optcountLoc = validOptsLoc.Count(); var score_resLoc = validOptsLoc.Select(x => score(x, player.PlayerId, (optcountLoc >= 5) ? ((optcountLoc >= 25) ? 1 : 2) : 3)).Where(x => (x.Key.Source == null || x.Key.Source.Cost <= mana || x.Value == Int32.MaxValue)).Where(x => Convert.ToString(x.Key).Contains("Fireblast") != true || mana >= 1).OrderBy(x => x.Value); /*Console.WriteLine("OPTS"); * * foreach (var tmp_score in score_resLoc) * { * * Console.WriteLine(Convert.ToString(tmp_score.Key) + Convert.ToString(tmp_score.Value)); * } * Console.WriteLine("-------------------------------------------------------"); * * Console.WriteLine("Round Nr:" + Convert.ToString(game.Turn)); * Console.WriteLine("HeroHP: " + Convert.ToString(player.Hero.Health) + "\tOppHP: " + Convert.ToString(game.CurrentOpponent.Hero.Health)); * Console.WriteLine("HeroMinionHP: " + Convert.ToString(player.BoardZone.Sum(p => p.Health)) + "\tOppMinionHP: " + Convert.ToString(game.CurrentOpponent.BoardZone.Sum(p => p.Health))); * Console.WriteLine("HeroMinionAtk: " + Convert.ToString(player.BoardZone.Sum(p => p.AttackDamage)) + "\tOppMinionAtk: " + Convert.ToString(game.CurrentOpponent.BoardZone.Sum(p => p.AttackDamage))); * Console.WriteLine("HeroNbMinions: " + Convert.ToString(player.BoardZone.Count) + "\tOppMinionNB: " + Convert.ToString(game.CurrentOpponent.BoardZone.Count)); * * //Console.WriteLine("OPTS:" + Convert.ToString(score_res.First())); * //Console.WriteLine("OPTS:" + Convert.ToString(score_res.Last())); * //Console.WriteLine("OPTS:" + Convert.ToString(score_res.Count())); */ if (score_resLoc.Count() > 1) { //Console.WriteLine("OPTION TAKEN" + Convert.ToString(score_resLoc.Last().Key)); return(score_resLoc.Last().Key); } //Console.WriteLine("REEEEEEEEEEENNNNNNNNNNNOOOOOOOOOOOOOOO:" + Convert.ToString(player.Hero.Health)); //Console.WriteLine("OPTS:" + Convert.ToString(opt1.First())); return(opt1.First()); } var returnValue = validOpts.Any() ? validOpts.Select(x => score(x, player.PlayerId, (optcount >= 5) ? ((optcount >= 25) ? 1 : 2) : 3)).OrderBy(x => x.Value).Where(x => Convert.ToString(x.Key).Contains("Reno Jackson") != true).Last().Key : player.Options().First(x => x.PlayerTaskType == PlayerTaskType.END_TURN); return(returnValue); KeyValuePair <PlayerTask, int> score(KeyValuePair <PlayerTask, POGame> state, int player_id, int max_depth = 3) { int max_score = int.MinValue; if (max_depth > 0 && state.Value.CurrentPlayer.PlayerId == player_id) { var subactions = state.Value.Simulate(state.Value.CurrentPlayer.Options()).Where(x => x.Value != null); foreach (var subaction in subactions) { max_score = Math.Max(max_score, score(subaction, player_id, max_depth - 1).Value); } } max_score = Math.Max(max_score, Score(state.Value, player_id)); return(new KeyValuePair <PlayerTask, int>(state.Key, max_score)); } }
public override PlayerTask GetMove(POGame game) { if (!initialized) { Initialize(game); } // if there is a subagent if (subAgent != null) { // let subagent do the move, skip the following code return(subAgent.GetMove(game)); } var player = game.CurrentPlayer; // Implement a simple Mulligan Rule if (player.MulliganState == Mulligan.INPUT) { List <int> mulligan = new CustomScore().MulliganRule().Invoke(player.Choice.Choices.Select(p => game.getGame().IdEntityDic[p]).ToList()); return(ChooseTask.Mulligan(player, mulligan)); } var opponent = game.CurrentOpponent; var options = player.Options(); var coins = options.Where(x => x.HasSource && x.Source.Card.Name == "The Coin"); if (coins.Count() > 0) { return(coins.First()); } var validOpts = game.Simulate(options).Where(x => x.Value != null); var optcount = validOpts.Count(); #if DEBUG /* * var score_res = validOpts.Select(x => score(x, player.PlayerId, (optcount >= 5) ? ((optcount >= 25) ? 1 : 2) : 3)).OrderBy(x => x.Value); * * Console.WriteLine("Round Nr:" + Convert.ToString(game.Turn)); * Console.WriteLine("HeroHP: " + Convert.ToString(player.Hero.Health) + "\tOppHP: " + Convert.ToString(game.CurrentOpponent.Hero.Health)); * Console.WriteLine("HeroMinionHP: " + Convert.ToString(player.BoardZone.Sum(p => p.Health)) + "\tOppMinionHP: " + Convert.ToString(game.CurrentOpponent.BoardZone.Sum(p => p.Health))); * Console.WriteLine("HeroMinionAtk: " + Convert.ToString(player.BoardZone.Sum(p => p.AttackDamage)) + "\tOppMinionAtk: " + Convert.ToString(game.CurrentOpponent.BoardZone.Sum(p => p.AttackDamage))); * foreach (var tmp_score in score_res) * { * * Console.WriteLine(Convert.ToString(tmp_score.Key) + Convert.ToString(tmp_score.Value)); * } * Console.WriteLine("-------------------------------------------------------"); * //PrintLog(game, score_res); */ #endif if (player.Hero.Health < DEFENSE_HEALTH_THRESHOLD * player.Hero.BaseHealth) { RuntimeScaling[0] += 0.1; } if (opponent.Hero.Health < DEFENSE_HEALTH_THRESHOLD * opponent.Hero.Health) { RuntimeScaling[1] += 0.1; } var returnValue = validOpts.Any() ? validOpts.Select(x => score(x, player.PlayerId, (optcount >= 5) ? ((optcount >= 25) ? 1 : 2) : 3)).OrderBy(x => x.Value).Last().Key : player.Options().First(x => x.PlayerTaskType == PlayerTaskType.END_TURN); return(returnValue); KeyValuePair <PlayerTask, int> score(KeyValuePair <PlayerTask, POGame> state, int player_id, int max_depth = 3) { int max_score = int.MinValue; if (max_depth > 0 && state.Value.CurrentPlayer.PlayerId == player_id) { var subactions = state.Value.Simulate(state.Value.CurrentPlayer.Options()).Where(x => x.Value != null); foreach (var subaction in subactions) { max_score = Math.Max(max_score, score(subaction, player_id, max_depth - 1).Value); } } max_score = Math.Max(max_score, Score(state.Value, player_id)); return(new KeyValuePair <PlayerTask, int>(state.Key, max_score)); } }
/* Cannot be used when using threads * public void PrintLog(POGame game, IOrderedEnumerable<KeyValuePair<PlayerTask, int>> scoreres) * { * var player = game.CurrentPlayer; * var validOpts = game.Simulate(player.Options()).Where(x => x.Value != null); * var score_res = scoreres; * Console.WriteLine("Round Nr:" + Convert.ToString(game.Turn)); * Console.WriteLine("HeroHP: " + Convert.ToString(player.Hero.Health) + "\tOppHP: " + Convert.ToString(game.CurrentOpponent.Hero.Health)); * Console.WriteLine("HeroMinionHP: " + Convert.ToString(player.BoardZone.Sum(p => p.Health)) + "\tOppMinionHP: " + Convert.ToString(game.CurrentOpponent.BoardZone.Sum(p => p.Health))); * Console.WriteLine("HeroMinionAtk: " + Convert.ToString(player.BoardZone.Sum(p => p.AttackDamage)) + "\tOppMinionAtk: " + Convert.ToString(game.CurrentOpponent.BoardZone.Sum(p => p.AttackDamage))); * foreach (var tmp_score in score_res) * { * * Console.WriteLine(Convert.ToString(tmp_score.Key) + Convert.ToString(tmp_score.Value)); * } * Console.WriteLine("-------------------------------------------------------"); * } */ public override PlayerTask GetMove(POGame game) { var player = game.CurrentPlayer; // Implement a simple Mulligan Rule if (player.MulliganState == Mulligan.INPUT) { List <int> mulligan = new CustomScore().MulliganRule().Invoke(player.Choice.Choices.Select(p => game.getGame().IdEntityDic[p]).ToList()); return(ChooseTask.Mulligan(player, mulligan)); } var opponent = game.CurrentOpponent; var options = player.Options(); var validOpts = game.Simulate(options).Where(x => x.Value != null); var optcount = validOpts.Count(); if (game.Turn == 1) { var opt1 = options.Where(x => x.HasSource && x.Source.Card.Name == "N'Zoth's First Mate"); if (opt1.Count() > 0) { /* * Console.WriteLine(opt1); * Console.WriteLine(opt1.First()); * Console.WriteLine(opt1.Last()); */ return(opt1.First()); } } if (game.Turn == 3) { var opt2 = options.Where(x => x.HasSource && x.Source.Card.Name == "Fiery War Axe"); if (opt2.Count() > 0) { return(opt2.First()); } } if (game.Turn == 5) { var opt2 = options.Where(x => x.HasSource && x.Source.Card.Name == "Arcanite Reaper"); if (opt2.Count() > 0) { return(opt2.First()); } } /* * if (player.Hero.Health < DEFENSE_HEALTH_THRESHOLD * player.Hero.BaseHealth) * RuntimeScaling[0] += 0.1; * * if (opponent.Hero.Health < DEFENSE_HEALTH_THRESHOLD * opponent.Hero.Health) * RuntimeScaling[1] += 0.1; */ var returnValue = validOpts.Any() ? validOpts.Select(x => score(x, player.PlayerId, (optcount >= 5) ? ((optcount >= 25) ? 1 : 2) : 3)).OrderBy(x => x.Value).Last().Key : player.Options().First(x => x.PlayerTaskType == PlayerTaskType.END_TURN); return(returnValue); KeyValuePair <PlayerTask, int> score(KeyValuePair <PlayerTask, POGame> state, int player_id, int max_depth = 3) { int max_score = int.MinValue; if (max_depth > 0 && state.Value.CurrentPlayer.PlayerId == player_id) { var subactions = state.Value.Simulate(state.Value.CurrentPlayer.Options()).Where(x => x.Value != null); foreach (var subaction in subactions) { max_score = Math.Max(max_score, score(subaction, player_id, max_depth - 1).Value); } } max_score = Math.Max(max_score, Score(state.Value, player_id)); return(new KeyValuePair <PlayerTask, int>(state.Key, max_score)); } }
public override PlayerTask GetMove(POGame game) { var player = game.CurrentPlayer; // Implement a simple Mulligan Rule if (player.MulliganState == Mulligan.INPUT) { List <int> mulligan = new CustomScore().MulliganRule().Invoke(player.Choice.Choices.Select(p => game.getGame().IdEntityDic[p]).ToList()); return(ChooseTask.Mulligan(player, mulligan)); } var validOpts = game.Simulate(player.Options()).Where(x => x.Value != null); var optcount = validOpts.Count(); var returnValue = validOpts.Any() ? validOpts.Select(x => score(x, player.PlayerId, (optcount >= 5) ? ((optcount >= 25) ? 1 : 2) : 3)).OrderBy(x => x.Value).Last().Key : player.Options().First(x => x.PlayerTaskType == PlayerTaskType.END_TURN); return(returnValue); KeyValuePair <PlayerTask, int> score(KeyValuePair <PlayerTask, POGame> state, int player_id, int max_depth = 3) { int max_score = int.MinValue; if (max_depth > 0 && state.Value.CurrentPlayer.PlayerId == player_id) { var subactions = state.Value.Simulate(state.Value.CurrentPlayer.Options()).Where(x => x.Value != null); foreach (var subaction in subactions) { max_score = Math.Max(max_score, score(subaction, player_id, max_depth - 1).Value); } } max_score = Math.Max(max_score, Score(state.Value, player_id)); return(new KeyValuePair <PlayerTask, int>(state.Key, max_score)); } }
public override PlayerTask GetMove(POGame poGame) { Console.WriteLine(poGame.PartialPrint()); var player = poGame.CurrentPlayer; // During Mulligan: select Random cards if (player.MulliganState == Mulligan.INPUT) { List <int> mulligan = RandomMulliganRule().Invoke(player.Choice.Choices.Select(p => poGame.getGame().IdEntityDic[p]).ToList()); return(ChooseTask.Mulligan(player, mulligan)); } List <PlayerTask> options = poGame.CurrentPlayer.Options(); int count = 0; foreach (PlayerTask option in options) { count++; Console.WriteLine("[" + count.ToString() + "] " + option); } bool success = false; int choice = 0; while (!success) { string input = Console.ReadLine(); choice = int.Parse(input); if (choice > 0 && choice <= count) { success = true; } else { Console.WriteLine("Please enter a number for the option you choose."); } } return(options[choice - 1]); }
public override PlayerTask GetMove(POGame poGame) { var player = poGame.CurrentPlayer; var opponent = poGame.CurrentOpponent; var validOpts = poGame.Simulate(player.Options()).Where(x => x.Value != null); var history = opponent.PlayHistory; if (player.MulliganState == Mulligan.INPUT) { List <int> mulligan = new MyScore().MulliganRule().Invoke(player.Choice.Choices.Select(p => poGame.getGame().IdEntityDic[p]).ToList()); return(ChooseTask.Mulligan(player, mulligan)); } updateProbabilities(); ActionEstimator = new ActionEstimator(DecksDict, ProbabilitiesDict); int optionsCount = validOpts.Count(); Console.WriteLine("Valid options for TestAgent: "); validOpts.ToList().ForEach(option => Console.WriteLine(option)); var action = validOpts.Any() ? validOpts.Select(option => Score(option, poGame.CurrentPlayer.PlayerId, (optionsCount >= 5) ? ((optionsCount >= 25) ? 1 : 2) : 3)).OrderBy(pair => pair.Value).Last().Key : player.Options().First(option => option.PlayerTaskType == PlayerTaskType.END_TURN); Console.WriteLine("TestAgent: " + action); return(action); void updateProbabilities() { /* ----------- Counting probabilities ------------ */ foreach (KeyValuePair <string, List <Card> > deck in DecksDict) { int similarCount = 0; var playedCards = history.Select(h => h.SourceCard).ToList(); var deckCards = deck.Value; var deckCardsDistinct = deckCards.Distinct().ToList(); playedCards .ForEach(playedCard => { deckCardsDistinct.ForEach(deckCard => { if (playedCard.Name == deckCard.Name) { similarCount++; } }); }); double probability = Math.Round((double)similarCount / deckCards.Count(), 2); ProbabilitiesDict[deck.Key] = probability; //if (probability > 0) Console.WriteLine(deck.Key + " has probability of " + ProbabilitiesDict[deck.Key] * 100 + "%"); } } }
public override PlayerTask GetMove(POGame poGame) { var player = poGame.CurrentPlayer; // Implement a simple Mulligan Rule if (player.MulliganState == Mulligan.INPUT) { List <int> mulligan = new ControlScore().MulliganRule().Invoke(player.Choice.Choices.Select(p => poGame.getGame().IdEntityDic[p]).ToList()); return(ChooseTask.Mulligan(player, mulligan)); } // Apply MCTS and do the best move PlayerTask action = null; try { if (mcts) { action = MCTS(poGame.getCopy()); } else { var legalMoves = poGame.Simulate(player.Options()).Where(x => x.Value != null); return(legalMoves.Any() ? legalMoves.OrderBy(x => Score(x.Value, player.PlayerId)).Last().Key : player.Options().First(x => x.PlayerTaskType == PlayerTaskType.END_TURN)); } } catch (NullReferenceException) { action = player.Options().First(x => x.PlayerTaskType == PlayerTaskType.END_TURN); } if (myDebug) { Console.WriteLine(); Console.WriteLine(poGame.FullPrint()); Console.WriteLine("Chose action: " + action); } return(action); }
public override PlayerTask GetMove(POGame game) { var player = game.CurrentPlayer; // Implement a simple Mulligan Rule if (player.MulliganState == Mulligan.INPUT) { List <int> mulligan = new AggroScore().MulliganRule().Invoke(player.Choice.Choices.Select(p => game.getGame().IdEntityDic[p]).ToList()); return(ChooseTask.Mulligan(player, mulligan)); } // Get all simulation results for simulations that didn't fail var validOpts = game.Simulate(player.Options()).Where(x => x.Value != null); // If all simulations failed, play end turn option (always exists), else best according to score function return(validOpts.Any() ? validOpts.OrderBy(x => Score(x.Value, player.PlayerId)).Last().Key : player.Options().First(x => x.PlayerTaskType == PlayerTaskType.END_TURN)); }
//POGame poGame2; public override PlayerTask GetMove(POGame poGame) { var player = poGame.CurrentPlayer; // Implement a simple Mulligan Rule if (player.MulliganState == Mulligan.INPUT) { List <int> mulligan = new CustomScore().MulliganRule().Invoke(player.Choice.Choices.Select(p => poGame.getGame().IdEntityDic[p]).ToList()); return(ChooseTask.Mulligan(player, mulligan)); } #if DEBUG Console.WriteLine($"root:{GetGameHashCode(poGame)}"); #endif PlayerTask bestAction = null; if (poGame.CurrentPlayer.Options().Count == 1) { bestAction = poGame.CurrentPlayer.Options()[0]; } else { stopwatchForThisTurn.Start(); long bestActionCode = 0; Trajectory trajectory = new Trajectory(); List <PlayerTask> taskToSimulate = new List <PlayerTask>(1); taskToSimulate.Add(null); POGame poGameRoot = poGame; Node root; long gameHashCodeRoot = GetGameHashCode(poGameRoot); if (!nodeHashMap.TryGetValue(gameHashCodeRoot, out root)) { root = new Node(); nodeHashMap.Add(gameHashCodeRoot, root); } Expand(root, poGameRoot); /*foreach (var child in root.edges) * { * Console.WriteLine(child.actionHashCode); * }*/ long think_time = (30 * 1000 - stopwatchForThisTurn.ElapsedMilliseconds) / Math.Max(3, 5 - movesInThisTurn); Stopwatch stopwatch = new Stopwatch(); stopwatch.Start(); //for (int itr = 0; itr < 100; ++itr) while (stopwatch.ElapsedMilliseconds <= think_time) { Node node = root; poGame = poGameRoot.getCopy(); long gameHashCode = gameHashCodeRoot; long actionHashCodeNext = 0; bool simulateResult = true; int index = 0; trajectory.Clear(); // traverse do { index = Select(node); /*if (index >= node.edges.Count) * { * Console.WriteLine($"{index}, {node.edges.Count}, {node == root}"); * Debugger.Break(); * }*/ actionHashCodeNext = node.edges[index].actionHashCode; // Until the end of my own turn if (actionHashCodeNext == 0) { trajectory.Add((node, index)); break; } taskToSimulate[0] = null; foreach (PlayerTask task in poGame.CurrentPlayer.Options()) { if (GetActionHashCode(task) == actionHashCodeNext) { taskToSimulate[0] = task; break; } } if (taskToSimulate[0] == null) { // Hash key conflict return(poGame.CurrentPlayer.Options().First()); /*foreach (PlayerTask task in poGame.CurrentPlayer.Options()) * { * Console.WriteLine($"{task}, {GetActionHashCode(task)}"); * } * Console.WriteLine("---"); * foreach (var edge in node.edges) * { * Console.WriteLine($"{edge.task}, {edge.actionHashCode}"); * } * poGame2 = node.poGame; * Console.WriteLine(poGame2.Turn); * Console.WriteLine(gameHashCode); * Console.WriteLine("---"); * foreach (var minion in poGame.CurrentPlayer.BoardZone) * { * Console.WriteLine(minion.CantAttackHeroes); * } * var tasks = poGame.CurrentPlayer.Options(); * foreach (PlayerTask task in tasks) * { * Console.WriteLine($"{task}, {GetActionHashCode(task)}"); * } * Debugger.Break();*/ } poGame = poGame.Simulate(taskToSimulate)[taskToSimulate[0]]; long gameHashCodeNext = GetGameHashCode(poGame); if (gameHashCode == gameHashCodeNext) { // loop node.edges.RemoveAt(index); continue; } gameHashCode = gameHashCodeNext; trajectory.Add((node, index)); if (!nodeHashMap.TryGetValue(gameHashCode, out node)) { node = new Node(); //node.poGame = poGame; nodeHashMap.Add(gameHashCode, node); } } while (node.edges != null); if (simulateResult == false) { continue; } if (actionHashCodeNext != 0) { #if DEBUG Console.WriteLine($"expand:{gameHashCode}"); #endif Expand(node, poGame); float value = Simulate(node, poGame); Backup(trajectory, value); } else { float value; if (node.edges[index].visitCount == 0) { value = ScoreToValue(Score(poGame)); } else { value = node.edges[index].totalValue / node.edges[index].visitCount; } Backup(trajectory, value); } } stopwatch.Stop(); //Console.WriteLine($"{think_time}, {root.visitCount}, {root.visitCount * 1000 / stopwatch.ElapsedMilliseconds} nps"); // Choose the most visited node float best = Single.MinValue; foreach (Edge child in root.edges) { if (child.visitCount >= best) { best = child.visitCount; bestActionCode = child.actionHashCode; } } // Choose an action with a matching hash code foreach (PlayerTask task in poGameRoot.CurrentPlayer.Options()) { if (GetActionHashCode(task) == bestActionCode) { bestAction = task; break; } } } stopwatchForThisTurn.Stop(); ++movesInThisTurn; if (bestAction.PlayerTaskType == PlayerTaskType.END_TURN) { //Console.WriteLine(movesInThisTurn); stopwatchForThisTurn.Reset(); movesInThisTurn = 0; nodeHashMap.Clear(); } return(bestAction); }
public override PlayerTask GetMove(POGame game) { Controller player = game.CurrentPlayer; if (h_score == -1) { determineScore(player); } // Implement a simple Mulligan Rule if (player.MulliganState == Mulligan.INPUT) { List <int> mulligan = new HarderMidRangeScore().MulliganRule().Invoke(player.Choice.Choices.Select(p => game.getGame().IdEntityDic[p]).ToList()); return(ChooseTask.Mulligan(player, mulligan)); } int depth; int beamWidth; // Check how much time we have left on this turn. The hard limit is 75 seconds so we already stop // beam searching when 60 seconds have passed, just to be sure. if (_watch.ElapsedMilliseconds < 30 * 1000) { // We still have ample time, proceed with beam search depth = 15; beamWidth = 12; } else { // Time is running out, just simulate one timestep now depth = 1; beamWidth = 1; Console.WriteLine("Over 30s in turn already. Pausing beam search for this turn!"); } _watch.Start(); PlayerTask move = BeamSearch(game, depth, playerbeamWidth: beamWidth, opponentBeamWidth: 1); _watch.Stop(); if (move.PlayerTaskType == PlayerTaskType.END_TURN) { _watch.Reset(); } return(move); }
public override PlayerTask GetMove(POGame poGame) { timeIsUp = false; timer = new Timer(28000); timer.Elapsed += whenTimeUp; timer.Enabled = true; Controller player = poGame.CurrentPlayer; playerId = player.PlayerId; if (player.MulliganState == Mulligan.INPUT) { List <int> mulligan = new AggroScore().MulliganRule().Invoke(player.Choice.Choices.Select(p => poGame.getGame().IdEntityDic[p]).ToList()); return(ChooseTask.Mulligan(player, mulligan)); } IEnumerable <KeyValuePair <PlayerTask, POGame> > validOpts = poGame.Simulate(player.Options()).Where(x => x.Value != null); int countOptions = validOpts.Count(); //AppendChildNodes(rootNode); int bestScore = Int32.MinValue; PlayerTask chosenTask = null; foreach (KeyValuePair <PlayerTask, POGame> option in validOpts) { int currentScore = MiniMax(0, option.Value, true, Int32.MinValue, Int32.MaxValue); //Console.WriteLine("Current Score: " + currentScore); if (currentScore > bestScore) { bestScore = currentScore; chosenTask = option.Key; } } //Console.WriteLine("Best Score: " + bestScore); if (chosenTask == null) { chosenTask = player.Options().First(x => x.PlayerTaskType == PlayerTaskType.END_TURN); } //Console.WriteLine("Zugzeit " + stopWatch.Elapsed); //Console.WriteLine("Best Task: " + chosenTask); return(chosenTask); }