コード例 #1
0
 public static void AddRange(this PowerHistory dest, PowerHistory src)
 {
     for (int i = 0; i < src.Full.Count; ++i)
     {
         dest.Add(src.Full[i]);
     }
 }
コード例 #2
0
        /// <summary>Initializes a new instance of the <see cref="Game"/> class.</summary>
        /// <param name="gameConfig">The game configuration.</param>
        /// <param name="setupHeroes"></param>
        public Game(GameConfig gameConfig, bool setupHeroes = true)
            : base(null, Card.CardGame, new Dictionary <GameTag, int>
        {
            [GameTag.ENTITY_ID] = GAME_ENTITYID,
            [GameTag.ZONE]      = (int)Enums.Zone.PLAY,
            [GameTag.CARDTYPE]  = (int)CardType.GAME
        })
        {
            _gameConfig       = gameConfig;
            Game              = this;
            GamesEventManager = new GameEventManager(this);

            _players[0] = new Controller(this, gameConfig.Player1Name, 1, 2);
            _players[1] = new Controller(this, gameConfig.Player2Name, 2, 3);

            // add power history create game
            if (History)
            {
                PowerHistory.Add(PowerHistoryBuilder.CreateGame(this, _players));
            }

            if (setupHeroes)
            {
                _players[0].AddHeroAndPower(Cards.HeroCard(gameConfig.Player1HeroClass));
                _players[1].AddHeroAndPower(Cards.HeroCard(gameConfig.Player2HeroClass));
            }

            TaskQueue = new TaskQueue(this);
            TaskStack = new TaskStack(this);
        }
コード例 #3
0
        /// <summary>Process the specified task.
        /// The game will execute the desired task and all effects coupled either
        /// directly or indirectly in synchronous manner.
        ///
        /// Call <see cref="Controller.Options(bool)"/> on the <see cref="CurrentPlayer"/>
        /// instance for tasks which are accepted as arguments.
        /// After this method returns, check <see cref="Controller.Options(bool)"/>
        /// again until only <see cref="EndTurnTask"/> remains, which will
        /// start the turn of <see cref="CurrentOpponent"/>.
        /// </summary>
        /// <param name="gameTask">The game task to execute.</param>
        public void Process(PlayerTask gameTask)
        {
            // start with no splits ...
            Splits = new List <Game>();

            Log(LogLevel.INFO, BlockType.PLAY, "Game", gameTask.FullPrint());

            // clear last power history
            PowerHistory.Last.Clear();

            // make sure that we only use task for this game ...
            gameTask.Game = this;
            gameTask.Process();

            // add enchantment and buff tag changes
            if (History)
            {
                Enchants.ForEach(p =>
                                 p.Effects.Keys.ToList().ForEach(t =>
                                                                 IdEntityDic.Values.ToList().ForEach(o =>
                                                                                                     PowerHistory.Add(PowerHistoryBuilder.TagChange(o.Id, t, o[t])))));

                foreach (var controller in _players)
                {
                    controller.Hero.Enchants.ForEach(p =>
                                                     p.Effects.Keys.ToList().ForEach(t =>
                                                                                     PowerHistory.Add(PowerHistoryBuilder.TagChange(Game.CurrentPlayer.Hero.Id, t, Game.CurrentPlayer.Hero[t]))));

                    //CurrentPlayer.Hero.Weapon?.Enchants.ForEach(p => p.IsEnabled());
                    //CurrentPlayer.Hero.Weapon?.Triggers.ForEach(p => p.IsEnabled());
                    //CurrentOpponent.Hero.Weapon?.Enchants.ForEach(p => p.IsEnabled());
                    //CurrentOpponent.Hero.Weapon?.Triggers.ForEach(p => p.IsEnabled());

                    controller.ControlledZones.Where(z => z != null).ToList().ForEach(z =>
                                                                                      z.Enchants.ForEach(p =>
                                                                                                         p.Effects.Keys.ToList().ForEach(t =>
                                                                                                                                         z.GetAll.ForEach(o =>
                                                                                                                                                          PowerHistory.Add(PowerHistoryBuilder.TagChange(o.Id, t, o[t]))))));
                }

                Characters.ForEach(c =>
                                   c.Enchants.ForEach(p =>
                                                      p.Effects.Keys.ToList().ForEach(t =>
                                                                                      PowerHistory.Add(PowerHistoryBuilder.TagChange(c.Id, t, c[t])))));
            }

            if (Splitting)
            {
                var finalSplits = SplitNode.GetSolutions(this, 10, 10000);
                Dump("Split", $"found {finalSplits.Count} final splits of {finalSplits.Sum(p => p.SameState + 1)}!");
                finalSplits.GroupBy(p => p.SameState)
                .Select(i => new { Word = i.Key, Count = i.Count() })
                .ToList().ForEach(p => Dump("Split", $" {p.Count},  with {p.Word} same states"));
                FinalSplits = finalSplits;
            }
        }
コード例 #4
0
ファイル: Game.cs プロジェクト: Lat0ur/Brimstone
        public Task <ActionResult> RunActionBlockAsync(BlockType Type, IEntity Source, List <QueueAction> Actions, IEntity Target = null, int Index = -2)
        {
#if _GAME_DEBUG
            DebugLog.WriteLine("Game " + GameId + ": Running " + Type + " for " + Source.ShortDescription + " => " + (Target?.ShortDescription ?? "no target"));
#endif
            int index = Index != -2 ? Index : (Type == BlockType.POWER || Type == BlockType.ATTACK ? -1 : 0);
            var block = new BlockStart(Type, Source, Target, index);
            PowerHistory?.Add(block);
            ActionQueue.StartBlock(Source, Actions, block);
            return(ActionQueue.ProcessBlockAsync());
        }
コード例 #5
0
        public static bool Remove(this PowerHistory powerHistory, Func <IPowerHistoryEntry, bool> p)
        {
            int count = powerHistory.Full.Count;

            var copy = new PowerHistory();

            powerHistory.Where(e => !p(e)).ForEach(e => copy.Add(e));

            powerHistory.Clear();
            powerHistory.AddRange(copy);
            return(count > powerHistory.Full.Count);
        }
コード例 #6
0
        public static PowerHistory Where(this PowerHistory ph, Func <IPowerHistoryEntry, bool> p)
        {
            var where = new PowerHistory();
            for (int i = 0; i < ph.Full.Count; ++i)
            {
                if (p(ph.Full[i]))
                {
                    where.Add(ph.Full[i]);
                }
            }

            return(where);
        }
コード例 #7
0
        /// <summary>
        /// Part of the state machine.
        /// Runs when STATE = RUNNING &amp;&amp; NEXTSTEP = MAIN_READY
        /// </summary>
        public void MainReady()
        {
            if (History)
            {
                PowerHistory.Add(PowerHistoryBuilder.BlockStart(BlockType.TRIGGER, CurrentPlayer.Id, "", 1, 0));
            }

            Characters.ForEach(p =>
            {
                p.NumTurnsInPlay++;
                p.NumAttacksThisTurn = 0;
            });

            Heroes.ForEach(p =>
            {
                p.Controller.NumCardsDrawnThisTurn              = 0;
                p.Controller.NumCardsPlayedThisTurn             = 0;
                p.Controller.NumMinionsPlayedThisTurn           = 0;
                p.Controller.NumOptionsPlayedThisTurn           = 0;
                p.Controller.NumFriendlyMinionsThatDiedThisTurn = 0;
            });

            CurrentPlayer.Hero.IsExhausted       = false;
            CurrentPlayer.Hero.Power.IsExhausted = false;
            foreach (var e in CurrentPlayer.BoardZone)
            {
                e.IsSummoned  = false;
                e.IsExhausted = false;
            }

            // De-activate combo buff
            CurrentPlayer.IsComboActive = false;

            CurrentPlayer.NumMinionsPlayerKilledThisTurn         = 0;
            CurrentOpponent.NumMinionsPlayerKilledThisTurn       = 0;
            CurrentPlayer.NumFriendlyMinionsThatAttackedThisTurn = 0;
            NumMinionsKilledThisTurn = 0;
            CurrentPlayer.HeroPowerActivationsThisTurn = 0;

            CurrentPlayer.NumElementalsPlayedLastTurn = CurrentPlayer.NumElementalsPlayedThisTurn;
            CurrentPlayer.NumElementalsPlayedThisTurn = 0;

            if (History)
            {
                PowerHistory.Add(PowerHistoryBuilder.BlockEnd());
            }

            // set next step
            NextStep = Step.MAIN_START_TRIGGERS;
        }
コード例 #8
0
        public static void AddRangeFirst(this PowerHistory dest, PowerHistory src)
        {
            var tmp = new PowerHistory();

            tmp.AddRange(src);

            for (int i = 0; i < dest.Full.Count; ++i)
            {
                tmp.Add(dest.Full[i]);
            }

            dest.Clear();
            dest.AddRange(tmp);
        }
コード例 #9
0
        //public static string PrintBoard(this HearthNode state, XmlWriter x)
        //{
        //	var str = new StringBuilder();

        //	x.WriteTurn(state.Game);

        //	str.AppendLine("------------");
        //	str.AppendLine($"| Turn {state.Game.Turn} |");
        //	str.AppendLine("------------");
        //	str.AppendLine("-----------------------------------------------------------------------------------------------------");
        //	str.AppendLine(state.Game.FullPrint() + "-----------------------------------------------------------------------------------------------------");
        //	str.AppendLine($"{(state.Game.CurrentPlayer == state.Game.Player1 ? $"{state.Game.Player1.Hero.Card.Name}" : $"{state.Game.Player2.Hero.Card.Name}")} is thinking...");

        //	return str.ToString();
        //}

        /// <summary>
        /// Sorts this PowerHistory to match the HSReplay xml structure
        /// </summary>
        /// <param name="powerHistory"></param>
        public static void HSReplaySort(this PowerHistory powerHistory)
        {
            var first  = new PowerHistory();
            var second = new PowerHistory();

            foreach (IPowerHistoryEntry e in powerHistory.Full)
            {
                if (e.PowerType == PowerType.CREATE_GAME)
                {
                    first.Add(e);
                }

                else if (e.PowerType == PowerType.FULL_ENTITY)
                {
                    var fe = (PowerHistoryFullEntity)e;
                    if (fe.Entity.Tags[GameTag.CONTROLLER] == 1)
                    {
                        first.Add(e);
                    }

                    else if (fe.Entity.Tags[GameTag.CONTROLLER] == 2)
                    {
                        second.Add(e);
                    }
                }
            }

            powerHistory.Remove(e => first.Full.Contains(e) || second.Full.Contains(e));

            first.AddRange(second);
            second.Clear();
            second.AddRange(powerHistory);

            powerHistory.Clear();
            powerHistory.AddRange(first);
            powerHistory.AddRange(second);
        }
コード例 #10
0
        /// <summary>
        /// Part of the state machine.
        /// Runs when STATE = RUNNING &amp;&amp; NEXTSTEP = MAIN_DRAW
        /// </summary>
        public void MainDraw()
        {
            if (History)
            {
                PowerHistory.Add(PowerHistoryBuilder.BlockStart(BlockType.TRIGGER, CurrentPlayer.Id, "", 0, 0));                 // turn start effect
            }
            //CurrentPlayer.NumCardsToDraw = 1;
            Generic.Draw(CurrentPlayer);

            if (History)
            {
                PowerHistory.Add(PowerHistoryBuilder.BlockEnd());
            }

            // set next step
            NextStep = Step.MAIN_START;
        }
コード例 #11
0
        /// <summary>
        /// Part of the state machine.
        /// Runs when STATE = RUNNING &amp;&amp; NEXTSTEP = MAIN_START_TRIGGERS
        /// </summary>
        public void MainStartTriggers()
        {
            CurrentPlayer.TurnStart = true;
            DeathProcessingAndAuraUpdate();

            if (History)
            {
                PowerHistory.Add(PowerHistoryBuilder.BlockStart(BlockType.TRIGGER, CurrentPlayer.Id, "", 8, 0));
            }

            if (History)
            {
                PowerHistory.Add(PowerHistoryBuilder.BlockEnd());
            }

            // set next step
            NextStep = Step.MAIN_RESOURCE;
        }
コード例 #12
0
ファイル: Game.cs プロジェクト: Lat0ur/Brimstone
        internal void OnBlockEmpty(BlockStart Block)
        {
#if _GAME_DEBUG
            DebugLog.WriteLine("Game " + GameId + ": Action block " + Block.Type + " for " + Entities[Block.Source].ShortDescription + " resolved");
#endif
            PowerHistory?.Add(new BlockEnd(Block.Type));

            if (Block.Type == BlockType.TRIGGER)
            {
                ActiveTriggers.TriggerResolved();
            }

            // Post-ATTACK or Post-final TRIGGER DEATHS block
            if (Block.Type == BlockType.ATTACK || (Block.Type == BlockType.TRIGGER && ActiveTriggers.QueuedTriggersCount == 0))
            {
                RunDeathCreationStepIfNeeded();
            }
        }
コード例 #13
0
        /// <summary>
        /// Part of the state machine.
        /// Runs when STATE = RUNNING &amp;&amp; NEXTSTEP = BEGIN_DRAW
        /// </summary>
        public void BeginDraw()
        {
            Log(LogLevel.VERBOSE, BlockType.PLAY, "Game", $"Begin Draw.");

            //FirstPlayer.NumCardsToDraw = 3;
            //FirstPlayer.Opponent.NumCardsToDraw = 4;

            _players.ToList().ForEach(p =>
            {
                // quest draw if there is
                var quest = p.DeckZone.GetAll.Where(q => q is Spell && ((Spell)q).IsQuest).FirstOrDefault();
                Generic.Draw(p, quest != null ? quest : null);
                Generic.Draw(p);
                Generic.Draw(p);

                if (p != FirstPlayer)
                {
                    // 4th card for second player
                    Generic.Draw(p);

                    var coin = FromCard(FirstPlayer.Opponent, Cards.FromId("GAME_005"), new Dictionary <GameTag, int>()
                    {
                        [GameTag.ZONE]     = (int)Enums.Zone.HAND,
                        [GameTag.CARDTYPE] = (int)CardType.SPELL,
                        [GameTag.CREATOR]  = FirstPlayer.Opponent.PlayerId
                    });
                    Generic.AddHandPhase(FirstPlayer.Opponent, coin);
                }

                p.NumTurnsLeft = 1;
            });

            Player1.TimeOut = 75;
            Player2.TimeOut = 75;

            // ending mulligan draw block
            if (History)
            {
                PowerHistory.Add(PowerHistoryBuilder.BlockEnd());
            }

            NextStep = _gameConfig.SkipMulligan ? Step.MAIN_BEGIN : Step.BEGIN_MULLIGAN;
        }
コード例 #14
0
        /// <summary>
        /// Part of the state machine.
        /// Runs when STATE = RUNNING &amp;&amp; NEXTSTEP = BEGIN_MULLIGAN
        /// </summary>
        public void BeginMulligan()
        {
            Log(LogLevel.VERBOSE, BlockType.PLAY, "Game", $"Begin Mulligan.");

            // starting mulligan draw block
            if (History)
            {
                PowerHistory.Add(PowerHistoryBuilder.BlockStart(BlockType.TRIGGER, this.Id, "", -1, 0));
            }

            Player1.MulliganState = Mulligan.INPUT;
            Player2.MulliganState = Mulligan.INPUT;

            Generic.CreateChoice.Invoke(Player1, this, ChoiceType.MULLIGAN, ChoiceAction.HAND, Player1.HandZone.Select(p => p.Id).ToList());
            Generic.CreateChoice.Invoke(Player2, this, ChoiceType.MULLIGAN, ChoiceAction.HAND, Player2.HandZone.Select(p => p.Id).ToList());

            // ending mulligan draw block
            if (History)
            {
                PowerHistory.Add(PowerHistoryBuilder.BlockEnd());
            }
        }
コード例 #15
0
        /// <summary>
        /// Part of the state machine.
        /// Runs when STATE = RUNNING.
        /// </summary>
        public void StartGame()
        {
            Log(LogLevel.INFO, BlockType.PLAY, "Game", "Starting new game now!");

            // setting up the decks ...
            _gameConfig.Player1Deck?.ForEach(p => Entity.FromCard(Player1, p, null, Player1.DeckZone));
            _gameConfig.Player2Deck?.ForEach(p => Entity.FromCard(Player2, p, null, Player2.DeckZone));
            if (_gameConfig.FillDecks)
            {
                Player1.DeckZone.Fill();
                Player2.DeckZone.Fill();
            }

            // set gamestats
            State = State.RUNNING;
            _players.ToList().ForEach(p => p.PlayState = PlayState.PLAYING);

            // starting mulligan draw block
            if (History)
            {
                PowerHistory.Add(PowerHistoryBuilder.BlockStart(BlockType.TRIGGER, this.Id, "", -1, 0));
            }

            // getting first player
            FirstPlayer = _gameConfig.StartPlayer < 0
                                ? _players[Util.Random.Next(0, 2)]
                                : _players[_gameConfig.StartPlayer - 1];
            CurrentPlayer = FirstPlayer;

            Log(LogLevel.INFO, BlockType.PLAY, "Game", $"Starting Player is {CurrentPlayer.Name}.");

            // first turn
            Turn = 1;

            // set next step
            NextStep = Step.BEGIN_FIRST;
        }
コード例 #16
0
ファイル: Game.cs プロジェクト: Lat0ur/Brimstone
        // Death checking phase
        internal void RunDeathCreationStepIfNeeded()
        {
#if _GAME_DEBUG
            DebugLog.WriteLine("Game " + GameId + ": Checking for death creation step");
#endif
            if (_deathCheckQueue.Count == 0)
            {
                return;
            }

            // We only have to check health because ToBeDestroyed cannot be reversed without the minion leaving play
            var dyingEntities =
                _deathCheckQueue.Where(
                    id => ((ICharacter)Entities[id]).MortallyWounded && Entities[id].Zone.Type == Brimstone.Zone.PLAY)
                .Select(id => (ICharacter)Entities[id]).ToList();

            if (dyingEntities.Count > 0)
            {
#if _GAME_DEBUG
                DebugLog.WriteLine("Game " + GameId + ": Running death creation step");
#endif
                PowerHistory?.Add(new BlockStart(BlockType.DEATHS, this));
            }

            // Death Creation Step
            bool gameEnd = false;
            foreach (var e in dyingEntities)
            {
#if _ACTIONS_DEBUG
                DebugLog.WriteLine("Game {0}: {1} dies", GameId, e.ShortDescription);
#endif
                // Queue deathrattles and OnDeath triggers before moving mortally wounded minion to graveyard
                // (they will be executed after the zone move)
                // TODO: Test that each queue resolves before the next one populates. If it doesn't, we can make queue populating lazy
                if (e is Minion)
                {
                    ActiveTriggers.Queue(TriggerType.OnDeath, e);
                }

                // NumMinionsPlayerKilledThisTurn seems to be the number of minions that died this turn
                // regardless of who or what killed what
                e.Controller.NumMinionsPlayerKilledThisTurn++;
                NumMinionsKilledThisTurn++;
                e.IsExhausted = false;

                // Move dead character to graveyard
                e.Zone = e.Controller.Graveyard;

                // TODO: Reset all minion tags to default
                if (e is Minion)
                {
                    var minion = ((Minion)e);
                    minion.Damage = 0;
                }

                // Hero death
                if (e is Hero)
                {
                    e.Controller.PlayState = PlayState.LOSING;
                    gameEnd = true;
                }
            }
            if (gameEnd)
            {
                GameWon();
            }

            if (dyingEntities.Count > 0)
            {
                PowerHistory?.Add(new BlockEnd(BlockType.DEATHS));
            }
            _deathCheckQueue.Clear();
        }