protected virtual void Dispose(bool disposing) { unexpectedTermination = false; if (playerHost != null) { RemotingServices.Disconnect(playerHost); playerHost.Dispose(); playerHost = null; } if (disposing) { playerTask = null; } if (startHostProcessTimer != null) startHostProcessTimer.Dispose(); if (hostProcess != null) hostProcess.Dispose(); }
public bool PlayGame(bool addToGameStats = true, bool debug = false) { SabberStoneCore.Model.Game game = new SabberStoneCore.Model.Game(gameConfig, setupHeroes); //var game = new Game(gameConfig, setupHeroes); player1.InitializeGame(); player2.InitializeGame(); AbstractAgent currentAgent; Stopwatch currentStopwatch; POGame poGame; PlayerTask playertask = null; Stopwatch[] watches = new[] { new Stopwatch(), new Stopwatch() }; bool printGame = false; game.StartGame(); if (gameConfig.SkipMulligan == false) { var originalStartingPlayer = game.CurrentPlayer; var originalStartinOpponent = game.CurrentOpponent; game.CurrentPlayer = originalStartingPlayer; currentAgent = gameConfig.StartPlayer == 1 ? player1 : player2; poGame = new POGame(game, debug); playertask = currentAgent.GetMove(poGame); game.Process(playertask); game.CurrentPlayer = originalStartinOpponent; currentAgent = gameConfig.StartPlayer == 1 ? player2 : player1; poGame = new POGame(game, debug); playertask = currentAgent.GetMove(poGame); game.Process(playertask); game.CurrentPlayer = originalStartingPlayer; game.MainReady(); } #if DEBUG try { #endif while (game.State != State.COMPLETE && game.State != State.INVALID) { //if (debug) //Console.WriteLine("Turn " + game.Turn); if (printGame) { //Console.WriteLine(MCGS.SabberHelper.SabberUtils.PrintGame(game)); printGame = false; } if (game.Turn >= maxTurns) { break; } currentAgent = game.CurrentPlayer == game.Player1 ? player1 : player2; Controller currentPlayer = game.CurrentPlayer; currentStopwatch = game.CurrentPlayer == game.Player1 ? watches[0] : watches[1]; poGame = new POGame(game, debug); currentStopwatch.Start(); playertask = currentAgent.GetMove(poGame); currentStopwatch.Stop(); game.CurrentPlayer.Game = game; game.CurrentOpponent.Game = game; if (debug) { //Console.WriteLine(playertask); } if (playertask.PlayerTaskType == PlayerTaskType.END_TURN) { printGame = true; } game.Process(playertask); } #if DEBUG } catch (Exception e) //Current Player loses if he throws an exception { Console.WriteLine(e.Message); Console.WriteLine(e.StackTrace); game.State = State.COMPLETE; game.CurrentPlayer.PlayState = PlayState.CONCEDED; game.CurrentOpponent.PlayState = PlayState.WON; if (addToGameStats && game.State != State.INVALID) { gameStats.registerException(game, e); } } #endif if (game.State == State.INVALID || (game.Turn >= maxTurns && repeatDraws)) { return(false); } if (addToGameStats) { gameStats.addGame(game, watches); Console.WriteLine("Player 1 wins: " + gameStats.PlayerA_Wins + ", Player 2 wins: " + gameStats.PlayerB_Wins); } player1.FinalizeGame(); player2.FinalizeGame(); return(true); }
public TySimResult(POGame state, PlayerTask task, float value) { this.state = state; this.value = value; this.task = task; }
float[] HardCodedOptionRating(POGame.POGame poGame, List <PlayerTask> options) { Controller me = poGame.CurrentPlayer; Controller op = poGame.CurrentOpponent; int hp = me.Hero.Health; int opHp = op.Hero.Health; int heroDamage = me.Hero.TotalAttackDamage; int opHeroDamage = op.Hero.TotalAttackDamage; int handZoneCount = me.HandZone.Count; int opHandZoneCount = op.HandZone.Count; float averageHandCost = me.HandZone.GetAll().Sum(p => p.Cost) / ((handZoneCount == 0)? 1 : handZoneCount); int remainingCards = me.DeckZone.Count; int opRemainingCards = op.DeckZone.Count; int numberOfMinions = me.BoardZone.Count; int minionTotHealth = me.BoardZone.Sum(p => p.Health); int minionTotAttack = me.BoardZone.Sum(p => p.AttackDamage); int minionTotTauntHp = me.BoardZone.Where(p => p.HasTaunt).Sum(p => p.Health); int opNumberOfMinions = op.BoardZone.Count; int opMinionTotHealth = op.BoardZone.Sum(p => p.Health); int opMinionTotAttack = op.BoardZone.Sum(p => p.AttackDamage); int opMinionTotTauntHp = op.BoardZone.Where(p => p.HasTaunt).Sum(p => p.Health); float[] result = new float[options.Count]; for (int i = 0; i < options.Count; i++) { PlayerTask curOption = options[i]; if (curOption.PlayerTaskType == PlayerTaskType.MINION_ATTACK) { Minion minion = (Minion)curOption.Source; if (curOption.Target.Card.Type == SabberStoneCore.Enums.CardType.HERO) { if (minion.AttackDamage > opHp) { result[i] = 1f; } if (minionTotAttack > 1.3f * opMinionTotAttack && minionTotHealth > 1.3f * opMinionTotHealth) { result[i] += 0.5f; } result[i] += 0.3f; } if (curOption.Target.Card.Type == SabberStoneCore.Enums.CardType.MINION) { Minion targetMinion = (Minion)curOption.Target; if (minionTotAttack < 0.8f * opMinionTotAttack && minionTotHealth < 0.8f * opMinionTotHealth && minion.Health > targetMinion.AttackDamage) { result[i] += 0.5f; } if (minion.Health > targetMinion.AttackDamage && minion.AttackDamage > targetMinion.Health) { result[i] += 0.5f; } } if (minionTotAttack > 1.2f * opMinionTotAttack && minionTotHealth > 1.2f * opMinionTotHealth && opMinionTotTauntHp < 5) { result[i] += 0.1f; } result[i] += 0.1f; } if (curOption.PlayerTaskType == PlayerTaskType.PLAY_CARD) { if (curOption.Source.Card.Type == SabberStoneCore.Enums.CardType.MINION) { if (opNumberOfMinions > numberOfMinions && opMinionTotHealth > minionTotHealth || opMinionTotAttack > minionTotAttack) { result[i] += 0.5f; } result[i] += 0.5f; if (numberOfMinions == 0 && numberOfMinions == 0) { result[i] += 0.4f; } } if (curOption.Source.Card.Type == SabberStoneCore.Enums.CardType.WEAPON) { if (me.Hero.Damage <= 0) { result[i] += 0.4f; } } if (curOption.Source.Card.Type == SabberStoneCore.Enums.CardType.SPELL) { Spell curSpell = (Spell)curOption.Source; if (curOption.HasTarget && curOption.Target.Card.Type == SabberStoneCore.Enums.CardType.HERO) { result[i] += 0.2f; } if (curOption.HasTarget == false) { result[i] += 0.1f; } } } if (curOption.PlayerTaskType == PlayerTaskType.HERO_POWER) { if (me.HeroClass == SabberStoneCore.Enums.CardClass.SHAMAN) { result[i] += 0.2f; } if (me.HeroClass == SabberStoneCore.Enums.CardClass.MAGE && curOption.Target.Controller == me) { result[i] = -1f; } result[i] += 0.1f; } if (me.BaseMana <= 3 && me.RemainingMana >= 2 && (curOption.PlayerTaskType == PlayerTaskType.HERO_POWER || curOption.PlayerTaskType == PlayerTaskType.PLAY_CARD)) { result[i] += 0.5f; } if (curOption.PlayerTaskType == PlayerTaskType.END_TURN && me.RemainingMana > 0.5f * me.BaseMana) { result[i] = -0.5f; } if (curOption.PlayerTaskType == PlayerTaskType.HERO_ATTACK) { if (curOption.Target is Minion) { Minion curTarget = (Minion)curOption.Target; if (hp > curTarget.AttackDamage && curTarget.Health < heroDamage) { result[i] += 0.5f; } } if (curOption.Target is Hero) { Hero curTarget = (Hero)curOption.Target; if (hp > curTarget.AttackDamage && curTarget.Health < heroDamage) { result[i] += 0.5f; } } else { result[i] += 0.2f; } } } return(result); /*for (int i = 0; i < options.Count; i++) * { * * if (options[i].PlayerTaskType == PlayerTaskType.PLAY_CARD) * { * if (options[i].Source.Card.Type == SabberStoneCore.Enums.CardType.MINION) * { * * if (bestCard == null || options[i].Source.Card.Cost > bestCard.Cost) * { * bestCard = options[i].Source.Card; * id = i; * } * } * * } * * if (options[i].PlayerTaskType == PlayerTaskType.MINION_ATTACK) * { * if (options[i].Target != null && options[i].Target.Card.Type == SabberStoneCore.Enums.CardType.HERO) * hardMinionAttackOptionRating[i] = 1; * } * }*/ }
public static bool Compare(this PlayerTask task1, PlayerTask task2) { return(task1.FullPrint().Equals(task2.FullPrint())); }
private PlayerTask PlanNextTurn(POGame.POGame poGame) { var options = poGame.CurrentPlayer.Options(); if (options.Count == 1) { return(options[0]); } else { var minionAttacks = new List <PlayerTask>(); var faceAttacks = new List <PlayerTask>(); var heroAttacks = new List <PlayerTask>(); PlayerTask heroFace = null; var cards = new List <PlayerTask>(); int ourHealth = poGame.CurrentPlayer.Hero.Health + poGame.CurrentPlayer.Hero.Armor; int hisHealth = poGame.CurrentOpponent.Hero.Health + poGame.CurrentOpponent.Hero.Armor; int totalFaceDamage = 0; int totalIncomingFaceDamage = 0; // sort the moves foreach (PlayerTask task in options) { if (task.PlayerTaskType == PlayerTaskType.MINION_ATTACK) { if (task.Target == poGame.CurrentOpponent.Hero) { faceAttacks.Add(task); if (task.Source is Minion) { totalFaceDamage += ((Minion)task.Source).AttackDamage; } } else { minionAttacks.Add(task); } } else if (task.PlayerTaskType == PlayerTaskType.PLAY_CARD || task.PlayerTaskType == PlayerTaskType.HERO_POWER) { cards.Add(task); } else if (task.PlayerTaskType == PlayerTaskType.HERO_ATTACK) { heroAttacks.Add(task); if (task.Target == poGame.CurrentOpponent.Hero) { totalFaceDamage += poGame.CurrentPlayer.Hero.AttackDamage; heroFace = task; } } } foreach (var card in poGame.CurrentOpponent.BoardZone) { totalIncomingFaceDamage += card.AttackDamage * (card.HasWindfury ? 2 : 1); } // section card play var cardToPlay = BestCard(cards, poGame); if (cardToPlay != null) { return(cardToPlay); } // section minion attacks else if (faceAttacks.Count > 0 || minionAttacks.Count > 0) { if (faceAttacks.Count > 0 && (totalFaceDamage > totalIncomingFaceDamage && ourHealth > hisHealth || totalFaceDamage >= hisHealth)) { return(faceAttacks[0]); } else if (minionAttacks.Count > 0 && totalIncomingFaceDamage > ourHealth) { return(BestBoardCleaner(minionAttacks)); } else if (faceAttacks.Count > 0) { return(faceAttacks[0]); } else if (minionAttacks.Count > 0) { return(BestBoardCleaner(minionAttacks)); } } // section hero attacks else if (heroAttacks.Count > 0) { if (heroFace != null && totalFaceDamage >= hisHealth) { return(heroFace); } else if (ourHealth > 15) { PlayerTask best = null; var bestScore = 0; foreach (var attack in heroAttacks.Except(new PlayerTask[] { heroFace })) { var target = (Minion)attack.Target; var currentScore = (target.HasDivineShield || target.Health > poGame.CurrentPlayer.Hero.AttackDamage) ? 0 : target.AttackDamage; if (currentScore > bestScore) { best = attack; bestScore = currentScore; } } if (best != null && ourHealth - bestScore > 10) { return(best); } } else if (heroFace != null) { return(heroFace); } } } return(options[0]); }
public bool PlayGame(bool addToGameStats = true) { Game game = new Game(gameConfig, setupHeroes); player1.InitializeGame(); player2.InitializeGame(); AbstractAgent currentAgent; Stopwatch currentStopwatch; POGame poGame; PlayerTask playertask = null; Stopwatch[] watches = new[] { new Stopwatch(), new Stopwatch() }; game.StartGame(); try { while (game.State != State.COMPLETE && game.State != State.INVALID) { if (debug) { Console.WriteLine("Turn " + game.Turn); } currentAgent = game.CurrentPlayer == game.Player1 ? player1 : player2; Controller currentPlayer = game.CurrentPlayer; currentStopwatch = game.CurrentPlayer == game.Player1 ? watches[0] : watches[1]; poGame = new POGame(game, debug); currentStopwatch.Start(); playertask = currentAgent.GetMove(poGame); currentStopwatch.Stop(); game.CurrentPlayer.Game = game; game.CurrentOpponent.Game = game; if (debug) { Console.WriteLine(playertask); } game.Process(playertask); } } catch (Exception e) //Current Player loses if he throws an exception { Console.WriteLine(e.Message); Console.WriteLine(e.StackTrace); game.State = State.COMPLETE; game.CurrentPlayer.PlayState = PlayState.CONCEDED; game.CurrentOpponent.PlayState = PlayState.WON; if (addToGameStats && game.State != State.INVALID) { gameStats.registerException(game, e); } } if (game.State == State.INVALID) { return(false); } if (addToGameStats) { gameStats.addGame(game, watches); } player1.FinalizeGame(); player2.FinalizeGame(); return(true); }
public virtual bool IsTakeTask(PlayerTask task) { return(task.Action == TaskAction.Take); }
public virtual bool IsExchangeTask(PlayerTask task) { return(task.Action == TaskAction.Exchange); }
public void OnOptionsBlock(KettleOptionsBlock optionsBlock) { // convert that option Console.WriteLine("AI OnOptionsBlock called."); if (optionsBlock.PlayerId != PlayerId) { return; } List <PlayerTask> options = Session.Game.CurrentPlayer.Options(); // Do AI shit PlayerTask option = DoAI(options); // Convert it to poweroptions PowerAllOptions poweroptions = PowerOptionsBuilder.AllOptions(Session.Game, new List <PlayerTask> { option }); // And create a kettle block for it KettleOption chosenoption = new KettleOptionsBlock(poweroptions, Session.Game.CurrentPlayer.PlayerId).Options[0]; int mainOptionIndex = 0; int subOptionIndex = 0; int target = 0; int position = 0; // Then we try and find the kettle option that matches foreach (KettleOption koption in optionsBlock.Options) { if (koption.Type != chosenoption.Type) { continue; } if (!OptionsMatch(chosenoption.MainOption, koption.MainOption)) { continue; } if ((chosenoption.SubOptions == null || chosenoption.SubOptions.Count == 0) != (koption.SubOptions == null || koption.SubOptions.Count == 0)) { continue; } if (chosenoption.SubOptions != null) { foreach (KettleSubOption suboption in chosenoption.SubOptions) { if (OptionsMatch(chosenoption.SubOptions[0], suboption)) { subOptionIndex = koption.SubOptions.IndexOf(suboption); break; } } } mainOptionIndex = optionsBlock.Options.IndexOf(koption); if (chosenoption.MainOption != null && chosenoption.MainOption.Targets != null) { target = chosenoption.MainOption.Targets[0]; } break; } if (option is PlayCardTask playCard) { position = playCard.ZonePosition; } KettleSendOption sendoption = new KettleSendOption(); sendoption.Id = optionsBlock.Id; sendoption.MainOption = mainOptionIndex; sendoption.SubOption = subOptionIndex; sendoption.Target = target; sendoption.Position = position; Adapter.SendMessage(sendoption); }
public virtual bool IsWaitTask(PlayerTask task) { return(task.Action == TaskAction.Wait); }
public static void RandomGames() { int total = 1; var watch = Stopwatch.StartNew(); var gameConfig = new GameConfig() { StartPlayer = -1, Player1Name = "FitzVonGerald", Player1HeroClass = CardClass.PALADIN, Player1Deck = new List <Card>() { Cards.FromName("Blessing of Might"), Cards.FromName("Blessing of Might"), Cards.FromName("Gnomish Inventor"), Cards.FromName("Gnomish Inventor"), Cards.FromName("Goldshire Footman"), Cards.FromName("Goldshire Footman"), Cards.FromName("Hammer of Wrath"), Cards.FromName("Hammer of Wrath"), Cards.FromName("Hand of Protection"), Cards.FromName("Hand of Protection"), Cards.FromName("Holy Light"), Cards.FromName("Holy Light"), Cards.FromName("Ironforge Rifleman"), Cards.FromName("Ironforge Rifleman"), Cards.FromName("Light's Justice"), Cards.FromName("Light's Justice"), Cards.FromName("Lord of the Arena"), Cards.FromName("Lord of the Arena"), Cards.FromName("Nightblade"), Cards.FromName("Nightblade"), Cards.FromName("Raid Leader"), Cards.FromName("Raid Leader"), Cards.FromName("Stonetusk Boar"), Cards.FromName("Stonetusk Boar"), Cards.FromName("Stormpike Commando"), Cards.FromName("Stormpike Commando"), Cards.FromName("Stormwind Champion"), Cards.FromName("Stormwind Champion"), Cards.FromName("Stormwind Knight"), Cards.FromName("Stormwind Knight") }, Player2Name = "RehHausZuckFuchs", Player2HeroClass = CardClass.PALADIN, Player2Deck = new List <Card>() { Cards.FromName("Blessing of Might"), Cards.FromName("Blessing of Might"), Cards.FromName("Gnomish Inventor"), Cards.FromName("Gnomish Inventor"), Cards.FromName("Goldshire Footman"), Cards.FromName("Goldshire Footman"), Cards.FromName("Hammer of Wrath"), Cards.FromName("Hammer of Wrath"), Cards.FromName("Hand of Protection"), Cards.FromName("Hand of Protection"), Cards.FromName("Holy Light"), Cards.FromName("Holy Light"), Cards.FromName("Ironforge Rifleman"), Cards.FromName("Ironforge Rifleman"), Cards.FromName("Light's Justice"), Cards.FromName("Light's Justice"), Cards.FromName("Lord of the Arena"), Cards.FromName("Lord of the Arena"), Cards.FromName("Nightblade"), Cards.FromName("Nightblade"), Cards.FromName("Raid Leader"), Cards.FromName("Raid Leader"), Cards.FromName("Stonetusk Boar"), Cards.FromName("Stonetusk Boar"), Cards.FromName("Stormpike Commando"), Cards.FromName("Stormpike Commando"), Cards.FromName("Stormwind Champion"), Cards.FromName("Stormwind Champion"), Cards.FromName("Stormwind Knight"), Cards.FromName("Stormwind Knight") }, FillDecks = false, Shuffle = true, SkipMulligan = false, Logging = true, History = true }; int turns = 0; int[] wins = new[] { 0, 0 }; for (int i = 0; i < total; i++) { var game = new Game(gameConfig); game.StartGame(); game.Process(ChooseTask.Mulligan(game.Player1, new List <int>())); game.Process(ChooseTask.Mulligan(game.Player2, new List <int>())); game.MainReady(); while (game.State != State.COMPLETE) { List <PlayerTask> options = game.CurrentPlayer.Options(); PlayerTask option = options[Rnd.Next(options.Count)]; //Console.WriteLine(option.FullPrint()); game.Process(option); } turns += game.Turn; if (game.Player1.PlayState == PlayState.WON) { wins[0]++; } if (game.Player2.PlayState == PlayState.WON) { wins[1]++; } Console.WriteLine("game ended"); // Console.Write(game.PowerHistory.ToString()); using (System.IO.StreamWriter file = new System.IO.StreamWriter(@"powerhistory.log")) { file.WriteLine(game.PowerHistory.Print()); } using (System.IO.StreamWriter file = new System.IO.StreamWriter(@"logger.log")) { foreach (LogEntry log in game.Logs) { file.WriteLine(log.ToString()); } } } watch.Stop(); Console.WriteLine($"{total} games with {turns} turns took {watch.ElapsedMilliseconds} ms => " + $"Avg. {watch.ElapsedMilliseconds / total} per game " + $"and {watch.ElapsedMilliseconds / (total * turns)} per turn!"); Console.WriteLine($"playerA {wins[0] * 100 / total}% vs. playerB {wins[1] * 100 / total}%!"); }
//Lightning Bolt: Deal 3 damage. Overload: (1) private static void LightningBolt(TyState playerState, TyState opponentState, Controller player, Controller opponent, PlayerTask task, Spell spell) { if (task.HasTarget) { //reward if the spell does NOT overkill an enemy: if (task.Target is Minion) { SpellDamageReward(playerState, opponentState, player, opponent, task, spell, 3, 1.25f); } } }
//Lightning Storm: Deal 2-3 damage to all enemy minions. Overload: (2) private static void LightningStorm(TyState playerState, TyState opponentState, Controller player, Controller opponent, PlayerTask task, Spell spell) { //give punishment when having less than this enemies: const int NUM_ENEMY_TARGETS = 3; playerState.BiasValue += (opponentState.NumMinionsOnBoard - NUM_ENEMY_TARGETS) * 1.25f; }
//Gain 1 Mana Crystal this turn only. private static void TheCoin(TyState playerState, TyState opponentState, Controller player, Controller opponent, PlayerTask task, Spell spell) { var curMana = player.GetAvailableMana(); var newMana = curMana + 1; bool enablesNewCards = false; for (int i = 0; i < player.HandZone.Count; i++) { IPlayable card = player.HandZone[i]; //if the card can only be played after using the coin, then it is not bad: if (card.Cost > curMana && card.Cost <= newMana) { enablesNewCards = true; break; } } //if the coin does not enable to play new cards, give punishment. if (!enablesNewCards) { playerState.BiasValue -= 100.0f; } }
public virtual bool IsConfirmTask(PlayerTask task) { return(task.Action == TaskAction.Confirm); }
public override PlayerTask GetMove(SabberStoneCoreAi.POGame.POGame poGame) { DateTime start = DateTime.Now; List <PlayerTask> options = poGame.CurrentPlayer.Options(); PlayerTask t = options[0]; //thisMoveSeconds = Rnd.Next((int)remainingTurnSeconds / 10, (int)remainingTurnSeconds/5);//一手秒隨機 //thisMoveSeconds = 10; Score.Score s = null; s = myScore; totalTime = 8; if (options.Count >= 20) { totalTime = totalTime * 1; } else if (options.Count < 20 && options.Count >= 10) { totalTime = totalTime * 0.75; } else if (options.Count < 10 && options.Count >= 5) { totalTime = totalTime * 0.5; } else if (options.Count < 5) { totalTime = totalTime * 0.25; } else { // } if (options.Count == 1) { t = options[0]; } else { //t = do_MCTS.do_MCTS.GetBestAction_second(poGame, remainingSeconds / (Math.Max(options.Count - actionCount, 1))); //Console.WriteLine("動作有:" + options.Count + "個"); t = do_MCTS.do_MCTS.GetBestAction_second(poGame, totalTime); //t = do_MCTS.do_MCTS.GetBestAction_second(poGame, thisMoveSeconds); //t = do_MCTS.do_MCTS.GetBestAction_iteration(poGame, 30); } double seconds = (DateTime.Now - start).TotalSeconds; //這次動作幾秒 //totalSecond += seconds; if (t.PlayerTaskType == PlayerTaskType.END_TURN) { //Console.WriteLine( "此回合共" + totalSecond + "秒"); //totalSecond = 0; remainingSeconds = 15; actionCount = 0; } else { remainingSeconds -= seconds; actionCount++; } /* * if (t.PlayerTaskType == PlayerTaskType.END_TURN) * { * Console.WriteLine( "此回合共" + totalSecond + "秒"); * totalSecond = 0; * remainingTurnSeconds = 75; * * } * else * { * * remainingTurnSeconds -= seconds; * * } */ return(t); }
private static void BrainDeadTest() { const int total = 5000; var totCards = Cards.AllStandard.ToList(); int totCardsCount = totCards.Count; int turns = 0; int[] wins = new[] { 0, 0 }; var watch = Stopwatch.StartNew(); for (int i = 0; i < total; i++) { Console.Clear(); ProgressBar(i, total); var game = new Game(new GameConfig { //StartPlayer = 1, FormatType = FormatType.FT_STANDARD, Player1HeroClass = Cards.HeroClasses[i % 9], Player2HeroClass = Cards.HeroClasses[(i + 1) % 9], FillDecks = true, Logging = true, History = false }); game.StartGame(); Console.WriteLine($"{(i > 0 ? turns / i : 0)} AVG. Turns, " + $"{totCards.Count} Stand. -> " + $"{game.Player1.HeroClass} vs. {game.Player2.HeroClass}"); int loopCount = 0; int prevOptionsCount = 0; while (game.State != State.COMPLETE) { List <PlayerTask> options = game.CurrentPlayer.Options(); PlayerTask option = options[Rnd.Next(options.Count)]; if (options.Count > 1 && option is EndTurnTask) { continue; } if (prevOptionsCount == options.Count) { loopCount++; } else { loopCount = 0; } prevOptionsCount = options.Count; if (loopCount > 10) { Console.WriteLine("Found bug ... need to be analysed!"); Console.WriteLine(""); Console.WriteLine($"is current player board full? {game.CurrentPlayer.BoardZone.IsFull}"); Console.WriteLine(""); Console.WriteLine(game.FullPrint()); Console.WriteLine(""); options.ForEach(p => { Console.WriteLine(p.FullPrint()); }); ShowLog(game, LogLevel.VERBOSE); Console.ReadKey(); } game.Process(option); } game.Logs.Clear(); turns += game.Turn; if (game.Player1.PlayState == PlayState.WON) { wins[0]++; } if (game.Player2.PlayState == PlayState.WON) { wins[1]++; } } watch.Stop(); Console.WriteLine($"{total} games with {turns} turns took {watch.ElapsedMilliseconds} ms => " + $"Avg. {watch.ElapsedMilliseconds / total} per game " + $"and {watch.ElapsedMilliseconds / (total * turns)} per turn!"); Console.WriteLine($"playerA {wins[0] * 100 / total}% vs. playerB {wins[1] * 100 / total}%!"); }
/// <summary> /// TODO: API /// </summary> /// <param name="oppGame"></param> /// <param name="opponent">the controller of the opponent</param> /// <param name="predicitionMap">the map with all predictions</param> /// <param name="newSimulations"></param> /// <returns></returns> private double simulateOpponentWithPrediction(double lowerTimeBound, double timePerLeaf, POGame.POGame oppGame, Controller opponent, List <Prediction> predicitionMap, ref Dictionary <POGame.POGame, List <MCTSNode> > newSimulations) { double predictionScore = 0; if (predicitionMap?.Any() ?? false) { int denominator = predicitionMap.Count; var scorings = predicitionMap.GroupBy(p => p.Deck.Scoring) .Select(c => new MCTSNode.ScoreExt(((double)c.Count() / denominator), c.Key)) .OrderByDescending(s => s.Value).ToList(); // the simulation time for one prediction double timePerPrediction = timePerLeaf / predicitionMap.Count; // use prediction for each game for (int i = 0; i < predicitionMap.Count; i++) { Prediction prediction = predicitionMap[i]; var setasideZone = opponent.ControlledZones[Zone.SETASIDE] as SetasideZone; setasideZone = new SetasideZone(opponent); // create deck zone List <Card> deckCards = prediction.Deck.Cards; var deckZone = opponent.ControlledZones[Zone.DECK] as DeckZone; deckZone = new DeckZone(opponent); createZone(opponent, deckCards, deckZone, ref setasideZone); deckZone.Shuffle(); // create hand zone List <Card> handCards = prediction.Hand.Cards; var handZone = opponent.ControlledZones[Zone.HAND] as HandZone; handZone = new HandZone(opponent); createZone(opponent, handCards, handZone, ref setasideZone); var oppLeafNodes = new List <MCTSNode>(); IScore oppStrategy = prediction.Deck.Scoring; // forward game POGame.POGame forwardGame = oppGame.getCopy(); // upper time bound for simulation the opponent using the current prediction double oppSimulationTime = lowerTimeBound + (i + 1) * timePerPrediction / 2; // simulate opponent's moves while (forwardGame != null && forwardGame.State == State.RUNNING && forwardGame.CurrentPlayer.Id == opponent.Id) { // simulate var oppRoot = new MCTSNode(opponent.Id, scorings, forwardGame, null, null); MCTSNode bestOppNode = simulate(oppSimulationTime, oppRoot, ref oppLeafNodes); // get solution List <PlayerTask> solutions = bestOppNode.GetSolution(); for (int j = 0; j < solutions.Count && (forwardGame != null); j++) { PlayerTask oppTask = solutions[j]; Dictionary <PlayerTask, POGame.POGame> dir = forwardGame.Simulate(new List <PlayerTask> { oppTask }); forwardGame = dir[oppTask]; if (forwardGame != null && forwardGame.CurrentPlayer.Choice != null) { break; } } } // upper time bound for simulation the player using the forwarded game double simulationTime = oppSimulationTime + timePerPrediction / 2; double score = 0; var leafs = new List <MCTSNode>(); // simulate player using forwarded opponent game while (forwardGame != null && forwardGame.State == State.RUNNING && forwardGame.CurrentPlayer.Id == _playerId) { // simulate var root = new MCTSNode(_playerId, new List <MCTSNode.ScoreExt> { new MCTSNode.ScoreExt(1.0, _scoring) }, forwardGame, null, null); MCTSNode bestNode = simulate(simulationTime, root, ref leafs); // get solution List <PlayerTask> solutions = bestNode.GetSolution(); for (int j = 0; j < solutions.Count && (forwardGame != null); j++) { PlayerTask task = solutions[j]; Dictionary <PlayerTask, POGame.POGame> dir = forwardGame.Simulate(new List <PlayerTask> { task }); forwardGame = dir[task]; if (forwardGame != null && forwardGame.CurrentPlayer.Choice != null) { break; } } // TODO: maybe penalty forwardGame == null score = bestNode.TotalScore; } predictionScore += score; if (forwardGame != null) { newSimulations.Add(forwardGame, leafs); } } } return(predictionScore); }
private static void PowerHistoryTest() { var game = new Game(new GameConfig { StartPlayer = 1, Player1HeroClass = CardClass.DRUID, //DeckPlayer1 = new List<Card> //{ // Cards.FromName("Raven Idol") //}, Player2HeroClass = CardClass.MAGE, SkipMulligan = false, Shuffle = false, FillDecks = true }); game.StartGame(); //List<PlayerTask> options; //options = game.CurrentPlayer.Options(); //Console.WriteLine($" *** - {game.CurrentPlayer.Name} options on {game.Turn}. - ***"); //options.ForEach(p => Console.WriteLine(p.FullPrint())); //Console.WriteLine("*** - START GAME - ***"); //Console.WriteLine(game.PowerHistory.Print(false)); //Console.WriteLine("*** - MULLIGAN PLAYER 1 - ***"); //Console.WriteLine(PowerChoicesBuilder.EntityChoices(game, game.Player1.Choice).Print()); //Console.WriteLine("*** - MULLIGAN PLAYER 2 - ***"); //Console.WriteLine(PowerChoicesBuilder.EntityChoices(game, game.Player2.Choice).Print()); game.Process(ChooseTask.Mulligan(game.Player1, new List <int>(game.Player1.Choice.Choices))); //options = game.CurrentPlayer.Options(); //Console.WriteLine($" *** - {game.CurrentPlayer.Name} options on {game.Turn}. - ***"); //options.ForEach(p => Console.WriteLine(p.FullPrint())); //Console.WriteLine(game.PowerHistory.Print(false)); game.Process(ChooseTask.Mulligan(game.Player2, new List <int> { })); //options = game.CurrentPlayer.Options(); //Console.WriteLine($" *** - {game.CurrentPlayer.Name} options on {game.Turn}. - ***"); //options.ForEach(p => Console.WriteLine(p.FullPrint())); //Console.WriteLine(game.PowerHistory.Print(false)); game.MainReady(); //options = game.CurrentPlayer.Options(); //Console.WriteLine($" *** - {game.CurrentPlayer.Name} options on {game.Turn}. - ***"); //options.ForEach(p => Console.WriteLine(p.FullPrint())); //Console.WriteLine(game.PowerHistory.Print(false)); //game.Process(ConcedeTask.Any(game.CurrentPlayer)); //Console.Write("*** - CONCEDE - ***"); //Console.Write(game.PowerHistory.Print(false)); //ShowLog(game, LogLevel.VERBOSE); //Console.WriteLine(PowerOptionsBuilder.AllOptions(game.CurrentPlayer.Id, game.CurrentPlayer.Options()).Print()); //game.Process(EndTurnTask.Any(game.CurrentPlayer)); //ShowLog(game, LogLevel.VERBOSE); //Console.WriteLine(PowerOptionsBuilder.AllOptions(game.CurrentPlayer.Id, game.CurrentPlayer.Options()).Print()); while (game.State != State.COMPLETE) { List <PlayerTask> options = game.CurrentPlayer.Options(); Console.WriteLine($" *** - {game.CurrentPlayer.Name} options on {game.Turn}. - ***"); options.ForEach(p => Console.WriteLine(p.FullPrint())); Console.WriteLine(PowerOptionsBuilder.AllOptions(game, options)?.Print()); PowerChoicesBuilder.EntityChoices(game, game.CurrentPlayer.Choice); PlayerTask option = options[Rnd.Next(options.Count)]; game.Process(option); } //foreach (var powerAllOptionse in game.AllOptionsMap) // Console.WriteLine($"{powerAllOptionse.Key} => {powerAllOptionse.Value.Print()}"); //foreach (var entityChoice in game.EntityChoicesMap) // Console.WriteLine($"{entityChoice.Key} => {entityChoice.Value.Print()}"); //foreach (var playables in game.IdEntityDic) //{ // Console.WriteLine($"{playables.Key} => {playables.Value}"); //} ShowLog(game, LogLevel.VERBOSE); }
public double Score(PlayerTask task, POGame game) { //outputOptional("[Scoring]: -- scoring called |TaskType: " + task.PlayerTaskType + "--"); double score = 0; double[] weights = { 4, 1, 1.2, 1.2, 1, 0.5, 1, 3, 4 }; int playerId = game.CurrentPlayer.PlayerId; Controller player = game.CurrentPlayer.PlayerId == playerId ? game.CurrentPlayer : game.CurrentOpponent; Controller enemy = game.CurrentPlayer.PlayerId == playerId ? game.CurrentOpponent : game.CurrentPlayer; // the problem was that I was only looking at the cards options but not at the overall pogame double totalMinAtkMe = totalMinion(player, "a"); double totalMinAtkOp = totalMinion(enemy, "a"); double totalMinHMe = totalMinion(player, "h"); double totalMinHOp = totalMinion(enemy, "h"); //score += player.Hero.Health; //score -= enemy.Hero.Health; if (totalMinAtkMe >= enemy.Hero.Health) { score += 20000; } score -= enemy.BoardZone.Count() * weights[0]; // I want the enemy to have low board card count //score += totalMinAtkMe * weights[1]; //score += totalMinHMe * weights[1]; score += (totalMinAtkMe - totalMinAtkOp) * 20; score += (player.Hero.Health - enemy.Hero.Health) * 30; score += (totalMinHMe - totalMinHOp) * 10; //score -= totalMinAtkOp * weights[2]; //score -= totalMinHOp * weights[3]; // and then I can look at the specific tasks effect on other cards if (task.PlayerTaskType == PlayerTaskType.END_TURN) { //outputOptional("[Scoring]: return MinValue because its end turn"); return(double.MinValue); } if (task.HasSource) { //sonst wirft es exceptions, ob es eine Karte ist if (task.PlayerTaskType == PlayerTaskType.PLAY_CARD) //Karte spielen, da gibt es Spells oder Minions { Card card = task.Source.Card; //outputOptional(task.ToString()); //outputOptional("[Scoring]: this is the task" + task.ToString()); if (card.Name.Contains("Coin")) // the coin that gives us one extra mana, when starting second { outputPriorityHigh("[Rare]: caught the coin"); foreach (var handCard in player.HandZone) { if (handCard.Card.Type == CardType.MINION && handCard.Cost == player.RemainingMana - 1) // the coin gives you one extra mana { score += 1000; } } } if (card.Type == CardType.SPELL) { // Spell begin if (task.HasTarget) { if (enemy.BoardZone.Contains(task.Target)) { if (card.ATK == task.Target.Health) { // if we can clear opponents card in one go //score += task.Target.Health; score += task.Target.AttackDamage + (task.Target.Health / task.Target.AttackDamage) * weights[5]; } else if (card.ATK < task.Target.Health) { //bad choice because we should clear opponents cards in one go, //score += task.Target.AttackDamage*weights[6]; } else if (card.ATK > task.Target.Health) { //kill enemey card in one go (spell card) BUT wasting attack //score += task.Target.AttackDamage *(task.Target.Health / card.ATK)* weights[7]; } } } else // es hat kein target, also eine Karte die großflaechig damage macht { //score += enemy.BoardZone.Count*weights[8]; // da flaechen damage schauen wie viele wir treffen koennen } } //Spell end if (card.Type == CardType.MINION) // playing a card from hand // not minion attack! { //minion type if (card.Health <= 0) { //score += (task.Target.Cost - card.Cost); } //outputOptional("[Scoring]: Minion Card" + card.ToString() + "| Cost: " + card.Cost + " | Remaining Mana: " + player.RemainingMana); score += player.RemainingMana / card.Cost; // this would prefer low cost cards but in late game high cost cards are good? } //Console.WriteLine("[Scoring]: calculated the score for " + card.ToString() + " : " + score); } if (task.PlayerTaskType == PlayerTaskType.HERO_ATTACK || task.PlayerTaskType == PlayerTaskType.HERO_POWER) // oder Hero Power? { //better use mana for playing cards //outputOptional("[Scoring]: caught a Hero attack/power " + task.ToString()); if (task.Target.Health > weights[9]) // I would like to have player.HeroAttackPower * 2 // so if it would take more than 2 activations of the hero power to kill the target punish it // if less or equal to 2 turn then go for it // differentiate between minions and enemy hero { //score -= task.Target.Health; score -= task.Target.Health; } else { //score += task.Target.Health; //maybe somehting better than just the target.Health? //score += task.Target.Health*(task.Target.AttackDamage+1); } } if (task.PlayerTaskType == PlayerTaskType.MINION_ATTACK) { //outputOptional("[Scoring]: caught a Minion Attack " + task.ToString()); //score += task.Target.Health + task.Target.AttackDamage; // attack enemies with more health first //but maybe better to also consider bots with low health but high damage } //outputOptional("[Scoring]: pre calculated the score for task " + task.ToString() + " : " + Math.Round(score,2)); } //outputOptional("[Scoring]: ---- final score calculated: " + Math.Round(score,2) + "---"); return(score); }
public static void OptionsTest() { const int total = 5000; var totCards = Cards.AllStandard.ToList(); int totCardsCount = totCards.Count; int turns = 0; int[] wins = new[] { 0, 0 }; var watch = Stopwatch.StartNew(); for (int i = 0; i < total; i++) { Console.Clear(); ProgressBar(i, total); var game = new Game(new GameConfig { //StartPlayer = 1, FormatType = FormatType.FT_STANDARD, Player1HeroClass = Cards.HeroClasses[i % 9], Player2HeroClass = Cards.HeroClasses[(i + 1) % 9], FillDecks = true, Logging = false, History = false }); game.StartGame(); //watch.Stop(); //game.Player1.Deck.ToList().ForEach(p => totCards.Where(n => n == p.Card).ToList().ForEach(n => totCards.Remove(n))); //game.Player2.Deck.ToList().ForEach(p => totCards.Where(n => n == p.Card).ToList().ForEach(n => totCards.Remove(n))); //watch.Start(); Console.WriteLine($"{(i > 0 ? turns / i : 0)} AVG. Turns, " + //$"{((double)totCardsCount/ totCards.Count):0.0%} Stand." + $"{totCards.Count} Stand. -> " + $"{game.Player1.HeroClass} vs. {game.Player2.HeroClass}"); while (game.State != State.COMPLETE) { List <PlayerTask> options = game.CurrentPlayer.Options(); //try //{ PlayerTask option = options[Rnd.Next(options.Count)]; if (option.PlayerTaskType == PlayerTaskType.PLAY_CARD) { totCards.Where(n => n == option.Source.Card).ToList().ForEach(n => totCards.Remove(n)); } //Console.WriteLine(option.FullPrint()); game.Process(option); //} //catch (Exception e) //{ // Console.WriteLine(e); // ShowLog(game, LogLevel.VERBOSE); // throw; //} } game.Logs.Clear(); turns += game.Turn; if (game.Player1.PlayState == PlayState.WON) { wins[0]++; } if (game.Player2.PlayState == PlayState.WON) { wins[1]++; } } watch.Stop(); Console.WriteLine($"{total} games with {turns} turns took {watch.ElapsedMilliseconds} ms => " + $"Avg. {watch.ElapsedMilliseconds / total} per game " + $"and {watch.ElapsedMilliseconds / (total * turns)} per turn!"); Console.WriteLine($"playerA {wins[0] * 100 / total}% vs. playerB {wins[1] * 100 / total}%!"); totCards.OrderBy(o => o.Id).ToList().ForEach(p => Console.WriteLine($" {p.Id} {p.Type} {p}")); }
string getStringFromPlayerTask(PlayerTask task) { string result = task.FullPrint(); return(result); }
public override PlayerTask GetMove(POGame poGame) { if (poGame.Turn != lastTurnCounter) { //Console.WriteLine("New turn " + poGame.Turn + "\n"); actionsToDo.Clear(); lastTurnCounter = poGame.Turn; mcts = new MCTS(poGame); actionsToDo = mcts.run(); } var player = poGame.CurrentPlayer; /* * Console.WriteLine("------------------------------------" + "\nCards on hand:\n" + String.Join(";\n", player.HandZone)); * Console.WriteLine("\nCurrent Turn and Mana:\n" + poGame.Turn + ";\n" + player.RemainingMana); * Console.WriteLine("\nCurrent Health and Enemy Health:\n" + player.Hero.Health + ";\n" + player.Opponent.Hero.Health); * * Console.WriteLine("\nCards on enemy field:\n" + String.Join(";\n", player.Opponent.BoardZone)); * if (player.Opponent.BoardZone.Where(p => p.HasTaunt).Sum(p => p.Health) > 0) * Console.WriteLine("Total taunt on enemy side:\n" + player.Opponent.BoardZone.Where(p => p.HasTaunt).Sum(p => p.Health)); * * Console.WriteLine("\nCards on own field:\n" + String.Join(";\n", player.BoardZone)); * if (player.BoardZone.Where(p => p.HasTaunt).Sum(p => p.Health) > 0) * Console.WriteLine("Total taunt on own side:\n" + player.BoardZone.Where(p => p.HasTaunt).Sum(p => p.Health)); */ if (actionsToDo.Any()) { PlayerTask task = actionsToDo[0]; actionsToDo.RemoveAt(0); return(task); } else { return(poGame.CurrentPlayer.Options().First(x => x.PlayerTaskType == PlayerTaskType.END_TURN)); } /* * * Root = new Node(); * * var player = poGame.CurrentPlayer; * * // simple Mulligan Rule * if (player.MulliganState == Mulligan.INPUT) * { * List<int> mulligan = new MidRangeScore().MulliganRule().Invoke(player.Choice.Choices.Select(p => poGame.getGame().IdEntityDic[p]).ToList()); * return ChooseTask.Mulligan(player, mulligan); * } * * // Get all valid options for this turn * var validOpts = poGame.Simulate(player.Options()).Where(x => x.Value != null); * validOpts.OrderBy(x => new MidRangeScore { Controller = player }.Rate()); * * // Build initial tree * foreach (KeyValuePair<PlayerTask, POGame> actionState in validOpts) * { * var appnode = new Node(); * appnode.state = actionState.Value; * appnode.nodeAction = actionState.Key; * appnode.Q = new MidRangeScore { Controller = player }.Rate(); //might be wrong * Root.childNodes.Append<Node>(appnode); * } * * // Stats output * List<PlayerTask> options = new List<PlayerTask>(); * if (validOpts.Any()) * { * Console.WriteLine("------------------------------------" + "\nCards on hand:\n" + String.Join(";\n", player.HandZone)); * Console.WriteLine("\nCurrent Turn and Mana:\n" + poGame.Turn + ";\n" + player.RemainingMana); * Console.WriteLine("\nCurrent Health and Enemy Health:\n" + player.Hero.Health + ";\n" + player.Opponent.Hero.Health); * * Console.WriteLine("\nCards on enemy field:\n" + String.Join(";\n", player.Opponent.BoardZone)); * if (player.Opponent.BoardZone.Where(p => p.HasTaunt).Sum(p => p.Health) > 0) * Console.WriteLine("Total taunt on enemy side:\n" + player.Opponent.BoardZone.Where(p => p.HasTaunt).Sum(p => p.Health)); * * Console.WriteLine("\nCards on own field:\n" + String.Join(";\n", player.BoardZone)); * if (player.BoardZone.Where(p => p.HasTaunt).Sum(p => p.Health) > 0) * Console.WriteLine("Total taunt on own side:\n" + player.BoardZone.Where(p => p.HasTaunt).Sum(p => p.Health)); * * options = poGame.CurrentPlayer.Options(); * * } * return options[Rnd.Next(options.Count)]; */ }
public void SetTask(PlayerTask task) { this.task = task; PlayerData.Instance.SaveData(); }
public static void CloneStabilityTest() { Console.WriteLine("Test started"); int n = 0; //for (int i = 0; i < TESTCOUNT; i++) Parallel.For(0, TESTCOUNT, i => { var config = new GameConfig { Player1HeroClass = (CardClass)rnd.Next(2, 11), Player2HeroClass = (CardClass)rnd.Next(2, 11), FillDecks = true, FillDecksPredictably = true, Shuffle = false, SkipMulligan = true, History = false, Logging = false, }; var game = new Game(config); game.StartGame(); List <PlayerTask> optionHistory = new List <PlayerTask>(); Queue <LogEntry> logs = new Queue <LogEntry>(); //try //{ do { //while (game.Logs.Count > 0) // logs.Enqueue(game.Logs.Dequeue()); game = game.Clone(); List <PlayerTask> options = game.CurrentPlayer.Options(); PlayerTask option = options[rnd.Next(options.Count)]; //optionHistory.Add(option); game.Process(option); } while (game.State != State.COMPLETE); //} catch (Exception e) //{ // ShowLog(logs, LogLevel.DEBUG); // Program.ShowLog(game, LogLevel.DEBUG); // Console.WriteLine(e.Message); // Console.WriteLine(e.Source); // Console.WriteLine(e.TargetSite); // Console.WriteLine(e.StackTrace); // PlayerTask last = optionHistory[optionHistory.Count - 1]; // Console.WriteLine($"LastOption: {last.FullPrint()}"); // break; //} Interlocked.Increment(ref n); if (n % (TESTCOUNT / 100) == 0) { Console.WriteLine($"{((double)n / TESTCOUNT) * 100}% done"); } //Console.Write("."); //optionHistory.Clear(); //logs.Clear(); } ); }
public void Process(PlayerTask task) { game.Process(task); }
public static void ThreadSafetyTest() { Console.WriteLine("Test started"); int i = 0; int num = System.Environment.ProcessorCount; while (i < TESTCOUNT * num) { var tasks = new Task[num]; var cts = new CancellationTokenSource(); var token = cts.Token; for (int j = 0; j < tasks.Length; j++) { tasks[j] = new Task(() => { var config = new GameConfig { Player1HeroClass = (CardClass)rnd.Next(2, 11), Player2HeroClass = (CardClass)rnd.Next(2, 11), FillDecks = true, FillDecksPredictably = true, Shuffle = false, SkipMulligan = true, History = false, //Logging = true, Logging = false }; var game = new Game(config); game.StartGame(); //List<PlayerTask> optionHistory = new List<PlayerTask>(); //Queue<LogEntry> logs = new Queue<LogEntry>(); PlayerTask option = null; try { do { //while (game.Logs.Count > 0) // logs.Enqueue(game.Logs.Dequeue()); game = game.Clone(true); List <PlayerTask> options = game.CurrentPlayer.Options(); option = options[rnd.Next(options.Count)]; //optionHistory.Add(option); game.Process(option); } while (game.State != State.COMPLETE); } catch (Exception e) { //ShowLog(logs, LogLevel.DEBUG); Program.ShowLog(game, LogLevel.DEBUG); Console.WriteLine(e.Message); Console.WriteLine(e.Source); Console.WriteLine(e.TargetSite); Console.WriteLine(e.StackTrace); Console.WriteLine($"LastOption: {option?.FullPrint()}"); cts.Cancel(); } if (token.IsCancellationRequested) { token.ThrowIfCancellationRequested(); } Interlocked.Increment(ref i); }, token); } for (int j = 0; j < tasks.Length; j++) { tasks[j].Start(); } Task.WaitAll(tasks); if (i % (TESTCOUNT * num / 10) == 0) { Console.WriteLine($"{((double) i / (TESTCOUNT * num)) * 100}% done"); } } }
public static bool IsBlocked(PlayerTask task, PlayerControl pc) { if (task == null || pc == null || pc != PlayerControl.LocalPlayer) { return(false); } bool isLights = task.TaskType == TaskTypes.FixLights; bool isComms = task.TaskType == TaskTypes.FixComms; bool isReactor = task.TaskType == TaskTypes.StopCharles || task.TaskType == TaskTypes.ResetSeismic || task.TaskType == TaskTypes.ResetReactor; bool isO2 = task.TaskType == TaskTypes.RestoreOxy; if (pc.isRole(RoleType.Swapper) && (isLights || isComms)) { return(true); } if (pc.hasModifier(ModifierType.Madmate) && (isLights || (isComms && !Madmate.canFixComm))) { return(true); } if (pc.hasModifier(ModifierType.CreatedMadmate) && (isLights || (isComms && !CreatedMadmate.canFixComm))) { return(true); } if (pc.isGM() && (isLights || isComms || isReactor || isO2)) { return(true); } if (pc.isRole(RoleType.Fox) && (isLights || isComms || isReactor || isO2)) { if (Fox.foxCanFixSabotageWhileStealth && Fox.isStealthed(pc)) { return(false); } else if (isLights || isComms) { return(true); } else if ((isO2 || isReactor) && !Fox.canFixReactorAndO2) { return(true); } } if (pc.isRole(RoleType.Mafioso) && !Mafioso.canRepair && (isLights || isComms)) { return(true); } if (pc.isRole(RoleType.Janitor) && !Janitor.canRepair && (isLights || isComms)) { return(true); } if (pc.isRole(RoleType.Fox) && (isLights || isComms || isReactor || isO2)) { if (isLights || isComms) { return(true); } else if ((isO2 || isReactor) && !Fox.canFixReactorAndO2) { return(true); } } return(false); }
public FlatMCOptionNode(FlatMCOptionNode parent, POGame.POGame game, int playerId, PlayerTask playerTask, IScore scoring) : base(parent, game, playerId, playerTask, scoring) { }
public PlayerHost(PlayerTask playerTask) { playbackController = playerTask.playbackController; playerTask.playbackController = this; this.playerTask = playerTask; }
public static void CalculateValues(TyState playerState, TyState opponentState, Controller player, Controller opponent, PlayerTask task, Spell spell) { if (_spellDictionary == null) { Init(); } //give reward/punishment if spells cost less/more than usual: float diff = (float)spell.Card.Cost - (float)spell.Cost; playerState.BiasValue += diff * 1.25f; var key = spell.Card.Name; if (_spellDictionary.ContainsKey(key)) { var action = _spellDictionary[key]; action(playerState, opponentState, player, opponent, task, spell); } else if (TyConst.LOG_UNKNOWN_SECRETS) { TyDebug.LogInfo("Unknown spell: " + task.FullPrint()); } }