private void LogMove(CardInPlay card, bool logPosition = false)
 {
     if (card.LastZone != card.CurrentZone)
     {
         if (logPosition)
         {
             Log.WriteLine(LogType.DebugVerbose, "{0},{1},{2},{3},{4},{5},{6},{7:0.000},{8:0.000},{9:0.000},{10:0.000}", card.Owner.ToString()[0],
                           card.LastNonEtherZone.ToString()[0], card.LastZone.ToString()[0], card.CurrentZone.ToString()[0], card.TheCard.Name, card.CardCode, TimeCounter,
                           card.NormalizedCenter.X, card.NormalizedCenter.Y, card.NormalizedBoundingBox.Width, card.NormalizedBoundingBox.Height);
         }
         else
         {
             Log.WriteLine(LogType.DebugVerbose, "{0},{1},{2},{3},{4},{5},{6}", card.Owner.ToString()[0],
                           card.LastNonEtherZone.ToString()[0], card.LastZone.ToString()[0], card.CurrentZone.ToString()[0], card.TheCard.Name, card.CardCode, TimeCounter);
         }
     }
 }
        void DrawElement(CardInPlay card, Graphics g, Color borderColor, Rectangle screenRect, bool flip)
        {
            float y = card.NormalizedBoundingBox.Y;

            if (flip)
            {
                y = 1 - y - card.NormalizedBoundingBox.Height;
            }
            Rectangle r = new Rectangle(
                (int)(0.5f + screenRect.Width / 2 + card.NormalizedBoundingBox.X * screenRect.Height),
                (int)(0.5f + y * screenRect.Height),
                (int)(0.5f + card.NormalizedBoundingBox.Width * screenRect.Height),
                (int)(0.5f + card.NormalizedBoundingBox.Height * screenRect.Height));

            r.Offset(screenRect.X, screenRect.Y);
            if (FullArtView)
            {
                card.TheCard.LoadCardArt();
                if (card.CurrentZone == PlayZone.Zoom || card.CurrentZone == PlayZone.Stage || card.CurrentZone == PlayZone.Hand || card.CurrentZone == PlayZone.Field)
                {
                    g.DrawImage(card.TheCard.CardArt, r);
                }
                else if (card.CurrentZone == PlayZone.Cast || card.CurrentZone == PlayZone.Battle || card.CurrentZone == PlayZone.Windup || card.CurrentZone == PlayZone.Attack)
                {
                    card.TheCard.DrawCardBanner(g, r);
                }
            }
            else
            {
                r.Offset(screenRect.X, screenRect.Y);
                g.DrawRectangle(new Pen(borderColor, 2), r);
                string text = string.Format("{0}\r\n{1}\r\n{2}\r\n{3}", CardLibrary.GetCard(card.CardCode).Name, card.CardCode,
                                            card.NormalizedCenter.Y, card.NormalizedBoundingBox.Height);
                TextRenderer.DrawText(g, text, this.Font, r, borderColor, TextFormatFlags.HorizontalCenter | TextFormatFlags.VerticalCenter);
            }
        }
Example #3
0
        /// <summary>
        /// Log moves for cards that appeared in a new zone, for a specific player
        /// </summary>
        /// <param name="last"></param>
        /// <param name="current"></param>
        /// <param name="opponentBattlingUnits">Opponent's battling units, used to find opposing unit in attack</param>
        /// <param name="isPlayerAttacking">If true, this player is attacking</param>
        private void LogMovedInCards(CardList <CardInPlay> last, CardList <CardInPlay> current, CardList <CardInPlay> opponentBattlingUnits, bool isPlayerAttacking)
        {
            bool[] logged = Enumerable.Repeat(false, current.Count).ToArray();
            // First remove exact mathces. This is important when multiple of the same card are in the same zone
            // Order of matching in that case does matter
            for (int i = 0; i < current.Count; i++)
            {
                CardInPlay card  = current[i];
                int        index = last.FindIndex(x => x.CardCode == card.CardCode && x.LastNonEtherZone == card.LastNonEtherZone && x.LastZone == card.LastZone);
                if (index >= 0)
                {
                    last.RemoveAt(index);
                    logged[i] = true;
                }
            }

            // Now look for moved cards
            for (int i = 0; i < current.Count; i++)
            {
                if (logged[i])
                {
                    continue;
                }

                CardInPlay card  = current[i];
                int        index = last.FindIndex(x => x.CardCode == card.CardCode);
                if (index >= 0)
                {
                    last.RemoveAt(index);
                }
                else if (card.CurrentZone != card.LastNonEtherZone)
                {
                    LogMove(card, opponentBattlingUnits, isPlayerAttacking);
                }
            }
        }
Example #4
0
        /// <summary>
        /// Log a single moved card
        /// </summary>
        /// <param name="card">Card to log</param>
        /// <param name="opponentBattlingUnits">Opponent's battling units, used to find opposing unit in attack</param>
        /// <param name="isPlayerAttacking">If true, this player is attacking</param>
        private void LogMove(CardInPlay card, CardList <CardInPlay> opponentBattlingUnits, bool isPlayerAttacking)
        {
            int     index;
            LogType logType = (card.Owner == PlayerType.LocalPlayer) ? LogType.Player : LogType.Opponent;
            string  action  = null;
            string  target  = "";

            switch (card.CurrentZone)
            {
            case PlayZone.Deck:
                if (card.LastNonEtherZone == PlayZone.Zoom)
                {
                    action = "Shuffled into Deck";
                }
                break;

            case PlayZone.Tossing:
                if (card.LastNonEtherZone == PlayZone.Deck)
                {
                    action = "Drawing from deck";
                }
                break;

            case PlayZone.Zoom:
                if (card.LastNonEtherZone == PlayZone.Deck)
                {
                    action = "Drawn from deck";
                }
                break;

            case PlayZone.Stage:
                if (card.LastNonEtherZone == PlayZone.Deck)
                {
                    action = "Presented";
                }
                break;

            case PlayZone.Hand:
                if (card.LastNonEtherZone == PlayZone.Field || card.LastNonEtherZone == PlayZone.Battle)
                {
                    action = "Recalled to Hand";
                }
                else if (card.LastNonEtherZone != PlayZone.Zoom)
                {
                    action = "Added to Hand";
                }
                break;

            case PlayZone.Cast:
                action = "Cast";
                break;

            case PlayZone.Field:
                if (card.LastNonEtherZone == PlayZone.Stage || card.LastNonEtherZone == PlayZone.Hand)
                {
                    action = "Played";
                }
                else if (card.LastNonEtherZone == PlayZone.Unknown || card.LastNonEtherZone == PlayZone.Tossing)
                {
                    action = "Summoned";
                }
                break;

            case PlayZone.Battle:
                //action = "Placed";
                break;

            case PlayZone.Windup:
                if (card.LastNonEtherZone != PlayZone.Attack)
                {
                    action  = "Attacking";
                    logType = LogType.Debug;
                }

                /*index = opponentBattlingUnits.FindIndex(x => Math.Abs(card.NormalizedCenter.X - x.NormalizedCenter.X) < 0.05);
                 * if (index == -1)
                 * {
                 *  target = " against Face";
                 * }
                 * else
                 * {
                 *  target = string.Format(" against {0}", opponentBattlingUnits[index].TheCard.Name);
                 * }*/
                break;

            case PlayZone.Attack:
                // Look for the opposing card the opposing
                action = isPlayerAttacking ? "Attacked" : "Defended";
                //if (card.LastNonEtherZone != PlayZone.Windup)
                {
                    index = opponentBattlingUnits.FindIndex(x => Math.Abs(card.NormalizedCenter.X - x.NormalizedCenter.X) < 0.05);
                    if (index == -1)
                    {
                        target = " hits Face";
                    }
                    else
                    {
                        target = string.Format(" hits {0}", opponentBattlingUnits[index].TheCard.Name);
                    }
                }
                //else
                //{
                //    logType = LogType.Debug;
                //}
                break;

            case PlayZone.Graveyard:
                logType = LogType.Debug;
                action  = (card.TheCard.Type == "Spell") ? "Resolved" : "Removed";
                break;

            case PlayZone.Ether:
            case PlayZone.Unknown:
                break;
            }
            if (action != null)
            {
                Log.WriteLine(logType, "[{0}{1}] {2}: {3}{4}", card.LastNonEtherZone.ToString()[0], card.CurrentZone.ToString()[0],
                              action, card.TheCard.Name, target);
            }
        }
        /// <summary>
        /// Process next rectangle layout
        /// </summary>
        /// <param name="overlay"></param>
        /// <param name="timestamp"></param>
        public void ProcessNext(Dictionary <string, JsonElement> overlay, double timestamp)
        {
            TimeCounter++;

            if (!TestMode && PlayerCards[(int)PlayZone.Deck].Count == 0 && PlayerCards[(int)PlayZone.Graveyard].Count == 0)
            {
                // Have not received the deck yet
                return;
            }
            CardList <CardInPlay> cardsInPlay = new CardList <CardInPlay>();

            bool isChampionUpgrading = false;

            if (overlay != null)
            {
                var screen = overlay["Screen"].ToObject <Dictionary <string, JsonElement> >();
                ScreenWidth  = screen["ScreenWidth"].GetInt32();
                ScreenHeight = screen["ScreenHeight"].GetInt32();

                // We normalize elements' bounding box based on screen height. However, if screen ratio becomes
                // too high, screen expands height-wise. To make sure we have same behavior as before,
                // We adjust the height accordingly.
                int normalizedScreenHeight = (int)(0.5 + GameBoard.ComputeNormalizedScreenHeight(ScreenWidth, ScreenHeight));

                Point correctionOffset = new Point(0, 0);
                var   rectangles       = overlay["Rectangles"].ToObject <Dictionary <string, JsonElement>[]>();
                foreach (var dict in rectangles)
                {
                    string cardCode = dict["CardCode"].GetString();
                    if (cardCode == "face")
                    {
                        if (dict["LocalPlayer"].GetBoolean())
                        {
                            int x = dict["TopLeftX"].GetInt32();
                            int y = dict["TopLeftY"].GetInt32();
                            if (IsInitialDraw)
                            {
                                LocalPlayerFace = new Point(x, y);
                            }
                            else
                            {
                                correctionOffset.X = LocalPlayerFace.X - x;
                                correctionOffset.Y = LocalPlayerFace.Y - y;
                            }
                        }

                        // We don't process face
                        continue;
                    }
                    Card card = CardLibrary.GetCard(cardCode);

                    // Also ignore abilities
                    if (card.Type != "Ability")
                    {
                        CardInPlay c = new CardInPlay(dict, ScreenWidth, ScreenHeight, correctionOffset, normalizedScreenHeight);
                        cardsInPlay.Add(card.Cost, card.Name, c);
                        if (c.CurrentZone == PlayZone.Hand && c.NormalizedCenter.Y > 1.3f)
                        {
                            // Champion is upgrading
                            isChampionUpgrading = true;
                        }
                    }
                }
            }

            // Split next elements between owners. Also, disregard cards with unknown zone
            CardList <CardInPlay> nextPlayerCards   = new CardList <CardInPlay>();
            CardList <CardInPlay> nextOpponentCards = new CardList <CardInPlay>();

            cardsInPlay.Split(ref nextPlayerCards, ref nextOpponentCards, x => x.Owner == PlayerType.LocalPlayer && x.CurrentZone != PlayZone.Unknown);
            Callback.OnElementsUpdate(nextPlayerCards, nextOpponentCards, ScreenWidth, ScreenHeight);
            if (isChampionUpgrading)
            {
                // Bail, champion is upgrading
                return;
            }

            if (nextPlayerCards.FindIndex(x => x.CurrentZone == PlayZone.Stage) >= 0)
            {
                CardsAreOnStage = true;
            }
            else if (CardsAreOnStage)
            {
                // Transition, reset ether timers
                for (int i = 0; i < PlayerCards[(int)PlayZone.Ether].Count; i++)
                {
                    PlayerCards[(int)PlayZone.Ether][i].EtherStartTime = timestamp;
                }
                CardsAreOnStage = false;
            }

            // Mark all opponent cards as "from deck" for now
            // This is because we cannot reliably know which ones are not from deck yet
            for (int i = 0; i < nextOpponentCards.Count; i++)
            {
                nextOpponentCards[i].IsFromDeck = nextOpponentCards[i].TheCard.IsCollectible;
            }

            MoveToNext(ref PlayerCards, nextPlayerCards, timestamp, IsInitialDraw, true);
            if (IsInitialDraw)
            {
                // Initial draw until we add some cards to hand
                IsInitialDraw = (PlayerCards[(int)PlayZone.Hand].Count() == 0);
            }


            MoveToNext(ref OpponentCards, nextOpponentCards, timestamp, false, false);

            // Purge Ether of spells that have been cast
            bool thoroughCleanUp = false;
            int  handCardIndex   = PlayerCards[(int)PlayZone.Hand].FindIndex(x => x.CurrentZone == PlayZone.Hand);

            if (PlayerCards[(int)PlayZone.Hand].Count() > 0 && PlayerCards[(int)PlayZone.Hand][0].NormalizedBoundingBox.Height < 0.235f)
            {
                thoroughCleanUp = true;
            }

            // Clean up ether -- generally move expired cards to graveyard, but also send cast champion spells back to deck
            if (!CardsAreOnStage)
            {
                // Find all the expiring
                CardList <CardInPlay> cardsGoingToGraveyard = CleanUpEther(ref PlayerCards[(int)PlayZone.Ether], timestamp, thoroughCleanUp);
                for (int i = 0; i < cardsGoingToGraveyard.Count; i++)
                {
                    if (cardsGoingToGraveyard[i].ChampionCode.Length > 0 && cardsGoingToGraveyard[i].TheCard.Type == "Spell")
                    {
                        var championCard       = CardLibrary.GetCard(cardsGoingToGraveyard[i].ChampionCode);
                        var championCardInPlay = new CardInPlay(championCard);
                        championCardInPlay.LastZone         = PlayZone.Ether;
                        championCardInPlay.LastNonEtherZone = cardsGoingToGraveyard[i].LastNonEtherZone;
                        championCardInPlay.CurrentZone      = PlayZone.Deck;
                        PlayerCards[(int)PlayZone.Deck].Add(championCard.Cost, championCard.Name, championCardInPlay);
                        cardsGoingToGraveyard[i].IsFromDeck = false;
                        Log.WriteLine(LogType.Player, "[{0}{1}] Shuffled back: {2}", championCardInPlay.LastNonEtherZone.ToString()[0],
                                      championCardInPlay.CurrentZone.ToString()[0], championCard.Name);
                    }
                }

                PlayerCards[(int)PlayZone.Graveyard].AddRange(cardsGoingToGraveyard);
            }
            OpponentCards[(int)PlayZone.Graveyard].AddRange(CleanUpEther(ref OpponentCards[(int)PlayZone.Ether], timestamp, true));

            NotifyCardSetUpdates();

            // Update attacking player
            int numPlayerAttackers   = PlayerCards[(int)PlayZone.Battle].Count + PlayerCards[(int)PlayZone.Windup].Count + PlayerCards[(int)PlayZone.Attack].Count;
            int numOpponentAttackers = OpponentCards[(int)PlayZone.Battle].Count + OpponentCards[(int)PlayZone.Windup].Count + OpponentCards[(int)PlayZone.Attack].Count;

            if (AttackingPlayer == PlayerType.None)
            {
                if (numPlayerAttackers != numOpponentAttackers)
                {
                    AttackingPlayer = numPlayerAttackers > numOpponentAttackers ? PlayerType.LocalPlayer : PlayerType.Opponent;
                }
            }
            else if (numPlayerAttackers == 0 && numOpponentAttackers == 0)
            {
                AttackingPlayer = PlayerType.None;
            }

            // Here we try to identify opponent's cards that did not start in deck
            // If a card appears in hand and we can see it, it was likely generated
            // Also, if a card appears in the field without going through stage first
            // it was likely generated by spell or another unit
            // Mark these cards as not from deck
            // Unfortunately, we have no way of tracking nabbed cards, so those will show up
            // as from deck
            for (int i = 0; i < OpponentCards[(int)PlayZone.Field].Count; i++)
            {
                if (OpponentCards[(int)PlayZone.Field][i].LastNonEtherZone == PlayZone.Unknown)
                {
                    OpponentCards[(int)PlayZone.Field][i].IsFromDeck = false;
                }
            }
            for (int i = 0; i < OpponentCards[(int)PlayZone.Hand].Count; i++)
            {
                if (OpponentCards[(int)PlayZone.Hand][i].LastNonEtherZone == PlayZone.Unknown)
                {
                    OpponentCards[(int)PlayZone.Hand][i].IsFromDeck = false;
                }
            }
        }