Exemplo n.º 1
0
        /**
         * Perform the core function for running the auto complete process.
         * This coroutine will rapidly move cards from the tableau to the foundation
         * and automatically complete the game once a valid winning state has been
         * determined by the system.
         */
        private IEnumerator AutoWinCoroutine()
        {
            SetDoingAutoWin(true);

            int attempts    = 0;
            int maxAttempts = 5000;

            // Build min priority queue based on all cards in tableau (prioritize lower value cards)
            PriorityQueue <Card> cardQueue = new PriorityQueue <Card>(true);

            // Add max attempts in case there is some corner case that occurs and causes a fail
            while (attempts < maxAttempts)
            {
                yield return(new WaitForEndOfFrame());

                // Break out of the loop if the win state has been met
                if (HasWon())
                {
                    break;
                }

                SnapManager[] tableauSnaps = tableau.GetComponentsInChildren <SnapManager>();
                foreach (SnapManager tableauSnap in tableauSnaps)
                {
                    // Get only the top card for now
                    Card topCard = tableauSnap.GetTopCard();
                    if (topCard != null)
                    {
                        cardQueue.Enqueue(topCard.value, topCard);
                    }
                }

                // Dequeue cards from priority queue and move each one to the foundation
                while (cardQueue.Count > 0)
                {
                    Card      priorityCard = cardQueue.Dequeue();
                    Transform nextMove     = GetNextAvailableMove(priorityCard);

                    // Only process move if one existed and if it is to a foundation
                    if (nextMove)
                    {
                        SnapManager currentSnapManager = priorityCard.GetComponentInParent <SnapManager>();
                        SnapManager nextSnapManager    = nextMove.GetComponent <SnapManager>();
                        bool        validMove          = nextSnapManager.belongingSection.Equals(Sections.FOUNDATIONS);
                        if (validMove)
                        {
                            // Make note of the current amount of attached cards
                            int currentCardCount = nextSnapManager.GetCardCount();

                            priorityCard.MoveTo(nextMove);

                            // Wait until the card is finished translating, is attached to the snap, and the current
                            // card count has incremented by one
                            yield return(new WaitUntil(() => {
                                return priorityCard.transform.parent != null &&
                                !priorityCard.IsTranslating() &&
                                nextSnapManager.GetCardCount() >= (currentCardCount + 1);
                            }));

                            // Add the current snap manager's top card to the priority queue
                            Card nextTopCard = currentSnapManager.GetTopCard();
                            if (nextTopCard != null)
                            {
                                cardQueue.Enqueue(nextTopCard.value, nextTopCard);
                            }
                        }
                    }
                }

                attempts++;
            }

            SetDoingAutoWin(false);
            m_autoWinComplete = true;
        }
Exemplo n.º 2
0
        /**
         * Move this card instance and/or other cards in it's card set to the specified target snap transform
         * @param Transform snap the target snap transform to move this card to
         * @param Card[] cardSet the set of dragged cards to handle translation all at once
         *                       with respect to this card instance. Defaults to null if a card set is not provided.
         *                       If the card set has only one card in it then it's assumed that the one card is
         *                       this card instance and will be processed as such.
         * @param MoveTypes moveType the type of move that determines how the move should be tracked in the GameManager.
         */
        public void MoveTo(Transform snap, Card[] cardSet = null, Move.MoveTypes moveType = Move.MoveTypes.NORMAL)
        {
            // Prepare the move object
            m_move     = new Move();
            m_moveType = moveType;

            // Set the target card based on value of card set
            // (if card set is null then create a new card set with this card as the only element)
            m_move.SetCards(cardSet ?? (new Card[] { this }));

            // We know that the card has/had a parent
            m_move.SetPreviousParent(m_startParent);

            // Need to get what the snap belongs to so that the card is placed in the correct location
            SnapManager snapManager    = snap.GetComponent <SnapManager>();
            bool        faceDownTarget = snapManager.HasCard() && snapManager.GetTopCard().IsFaceDown();

            GameManager.Sections targetSection = snapManager.belongingSection;

            // Set the next parent in the move
            m_move.SetNextParent(snapManager.transform);

            // Need to target the top card in the respective tableau pile and offset the y and z positions
            Transform tableauHasCardTarget = targetSection.Equals(GameManager.Sections.TABLEAU) && snapManager.HasCard() ?
                                             snapManager.GetTopCard().transform : snap;

            // Setting for reference to new parent snap
            m_targetTranslateSnap = snap;
            m_targetTranslatePos  = m_targetTranslateSnap.position; // Defaults to target snap position

            // Keep track of the starting position
            m_startPos = transform.position;

            m_draggedCards = cardSet;

            // Tell the snap manager currently associated with the card(s) to wait until animations are complete
            SnapManager currentSnap = GetComponentInParent <SnapManager>();

            if (currentSnap != null)
            {
                // Set the start parent here so that the current snap can be told to stop waiting later
                SetStartParent(currentSnap.transform);
                currentSnap.SetWaiting(true);
            }

            // Process a bit differently if a card set has been provided
            if (m_draggedCards != null && m_draggedCards.Length > 1)
            {
                // Do a first pass-through to remove parent and bring z-value of each of the dragged cards
                // to the z-offset dragging value
                for (int i = 0; i < m_draggedCards.Length; i++)
                {
                    Card draggedCard = m_draggedCards[i];
                    draggedCard.transform.parent = null;

                    // Keep track of each card's starting position
                    draggedCard.SetStartPos(draggedCard.transform.position);

                    float yOffset;
                    // Apply y-offset when dragging multiple cards (start without y-offset if there isn't a card on the snap)
                    // Handle case when action was an undo and the top card in the target snap is facedown
                    // (only the first card in the the set of dragged cards should have the face down y-offset applied in this case).
                    if (faceDownTarget && i == 0)
                    {
                        yOffset = GameManager.FACE_DOWN_Y_OFFSET;
                    }
                    else
                    {
                        if (faceDownTarget)
                        {
                            // Need to compensate for the fact that the first card applied face down y-offset
                            yOffset = (GameManager.FOUNDATION_Y_OFFSET * i) + GameManager.FACE_DOWN_Y_OFFSET;
                        }
                        else
                        {
                            // Process normally (e.g., not undoing a flip event)
                            yOffset = GameManager.FOUNDATION_Y_OFFSET * (snapManager.HasCard() ? i + 1 : i);
                        }
                    }

                    Vector3 newTargetPos = new Vector3(
                        tableauHasCardTarget.position.x,
                        tableauHasCardTarget.position.y - yOffset,
                        tableauHasCardTarget.position.z - (i + 1)
                        );

                    // Set the new translate position for the dragged card
                    draggedCard.SetTargetTranslatePosition(newTargetPos);

                    // Set the z-value of the transform to move to be high enough to hover over all other cards
                    draggedCard.transform.position = new Vector3(
                        draggedCard.transform.position.x,
                        draggedCard.transform.position.y,
                        -(GameManager.Z_OFFSET_DRAGGING + i)
                        );
                }
            }
            else // Otherwise, process on one card
            {
                // transform position is a special case for the Tableau cards due to y-offset in addition to z-offset
                if (targetSection.Equals(GameManager.Sections.TABLEAU) && snapManager.HasCard())
                {
                    Vector3 newTargetPos = new Vector3(
                        tableauHasCardTarget.position.x,
                        tableauHasCardTarget.position.y - (faceDownTarget ? GameManager.FACE_DOWN_Y_OFFSET : GameManager.FOUNDATION_Y_OFFSET),
                        tableauHasCardTarget.position.z - 1
                        );

                    m_targetTranslatePos = newTargetPos;
                }

                transform.parent = null;         // Temporarily detatch from the parent
                SetStartPos(transform.position); // Keep track of this card instance start position

                // Set the z-value of the transform to move to be high enough to hover over all other cards
                transform.position = new Vector3(
                    transform.position.x,
                    transform.position.y,
                    -GameManager.Z_OFFSET_DRAGGING
                    );
            }

            // Add the move to the game manager instance (only if normal move and not undone or redone)
            if (moveType == Move.MoveTypes.NORMAL)
            {
                GameManager.Instance.AddMove(m_move, moveType);
            }

            // Track the total number of moves with stats manager
            StatsManager.Instance.TallyMove();

            // Begin the translating animation
            m_translating = true;
        }