/// <summary> /// Adds a new Hero entity and HeroPower entity to the game instance. /// </summary> /// <param name="heroCard">The card to derive the hero entity from.</param> /// <param name="powerCard">The heropower card to derive the hero power entity from.</param> /// <param name="tags">The inherited tags</param> /// <param name="id">The entity id to assign to the generated HERO entity</param> public void AddHeroAndPower(Card heroCard, Card powerCard = null, Dictionary <GameTag, int> tags = null, int id = -1) { // remove hero and place it to the setaside zone Weapon weapon = null; if (Hero != null) { SetasideZone.MoveTo(Hero, SetasideZone.Count); SetasideZone.MoveTo(Hero.Power, SetasideZone.Count); //Hero[GameTag.EXHAUSTED] = 0; //Hero[GameTag.NUM_ATTACKS_THIS_TURN ] = 0; //Hero[GameTag.DAMAGE] = 0; //Hero[GameTag.REVEALED] = 1; if (Hero.Weapon != null) { weapon = Hero.Weapon; } } Hero = FromCard(this, heroCard, tags, null, id) as Hero; HeroId = Hero.Id; Hero.Power = FromCard(this, powerCard ?? Cards.FromAssetId(Hero[GameTag.HERO_POWER]), new Dictionary <GameTag, int> { [GameTag.CREATOR] = Hero.Id }) as HeroPower; Hero.Weapon = weapon; }
/// <summary> /// Creates a zone for the opponent using the specified cards and zone. /// </summary> /// <param name="opponent">the controller of the opponent</param> /// <param name="predictedCards">the predicted cards the zone is populated with</param> /// <param name="zone">the zone who will be created</param> /// <param name="setasideZone">the setaside zone</param> /// <returns>the playables of the zone based on the cards</returns> private List <IPlayable> createZone(Controller opponent, List <Card> predictedCards, IZone zone, ref SetasideZone setasideZone) { var deck = new List <IPlayable>(); foreach (Card card in predictedCards) { var tags = new Dictionary <GameTag, int>(); tags[GameTag.ENTITY_ID] = opponent.Game.NextId; tags[GameTag.CONTROLLER] = opponent.PlayerId; tags[GameTag.ZONE] = (int)zone.Type; IPlayable playable = null; switch (card.Type) { case CardType.MINION: playable = new Minion(opponent, card, tags); break; case CardType.SPELL: playable = new Spell(opponent, card, tags); break; case CardType.WEAPON: playable = new Weapon(opponent, card, tags); break; case CardType.HERO: tags[GameTag.ZONE] = (int)SabberStoneCore.Enums.Zone.PLAY; tags[GameTag.CARDTYPE] = card[GameTag.CARDTYPE]; playable = new Hero(opponent, card, tags); break; case CardType.HERO_POWER: tags[GameTag.COST] = card[GameTag.COST]; tags[GameTag.ZONE] = (int)SabberStoneCore.Enums.Zone.PLAY; tags[GameTag.CARDTYPE] = card[GameTag.CARDTYPE]; playable = new HeroPower(opponent, card, tags); break; default: throw new EntityException($"Couldn't create entity, because of an unknown cardType {card.Type}."); } opponent.Game.IdEntityDic.Add(playable.Id, playable); // add entity to the appropriate zone if it was given zone?.Add(playable); if (playable.ChooseOne) { playable.ChooseOnePlayables[0] = Entity.FromCard(opponent, Cards.FromId(playable.Card.Id + "a"), new Dictionary <GameTag, int> { [GameTag.CREATOR] = playable.Id, [GameTag.PARENT_CARD] = playable.Id }, setasideZone); playable.ChooseOnePlayables[1] = Entity.FromCard(opponent, Cards.FromId(playable.Card.Id + "b"), new Dictionary <GameTag, int> { [GameTag.CREATOR] = playable.Id, [GameTag.PARENT_CARD] = playable.Id }, setasideZone); } deck.Add(playable); } return(deck); }
/// <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); }