public static int DifferencePieceCounts(PieceCount a, PieceCount b)
 {
     return(Mathf.Abs(a.m_cannonballCount - b.m_cannonballCount)
            + Mathf.Abs(a.m_parchmentCount - b.m_parchmentCount)
            + Mathf.Abs(a.m_jewelCount - b.m_jewelCount)
            + Mathf.Abs(a.m_bottleCount - b.m_bottleCount));
 }
 // Returns true if the piece counts in a are greater-than or equal to b
 public static bool GtePieceCounts(PieceCount a, PieceCount b)
 {
     return(a.m_cannonballCount >= b.m_cannonballCount &&
            a.m_parchmentCount >= b.m_parchmentCount &&
            a.m_jewelCount >= b.m_jewelCount &&
            a.m_bottleCount >= b.m_bottleCount);
 }
 public Card(string id, Player playerA, PieceCount aWillGive, Player playerB, PieceCount bWillGive)
 {
     m_id        = id;
     m_playerA   = playerA;
     m_aWillGive = aWillGive;
     m_playerB   = playerB;
     m_bWillGive = bWillGive;
 }
    public static PieceCount SubtractPieceCounts(PieceCount a, PieceCount b)
    {
        PieceCount c;

        c.m_cannonballCount = a.m_cannonballCount - b.m_cannonballCount;
        c.m_parchmentCount  = a.m_parchmentCount - b.m_parchmentCount;
        c.m_jewelCount      = a.m_jewelCount - b.m_jewelCount;
        c.m_bottleCount     = a.m_bottleCount - b.m_bottleCount;
        return(c);
    }
    public PieceCount[] CalculateFinalCounts(List <Card>[] cards)
    {
        PieceCount[] pieceCounts = new PieceCount[4] {
            new PieceCount(m_starting_item_count, m_starting_item_count, m_starting_item_count, m_starting_item_count),
            new PieceCount(m_starting_item_count, m_starting_item_count, m_starting_item_count, m_starting_item_count),
            new PieceCount(m_starting_item_count, m_starting_item_count, m_starting_item_count, m_starting_item_count),
            new PieceCount(m_starting_item_count, m_starting_item_count, m_starting_item_count, m_starting_item_count),
        };
        for (int i = 0; i < 4; i++)
        {
            foreach (var card in cards[i])
            {
                ProcessCard(pieceCounts, card);
            }
        }

        return(pieceCounts);
    }
    public List <Card>[] DistributeCards()
    {
        PieceCount[] pieceCounts = new PieceCount[4] {
            new PieceCount(m_starting_item_count, m_starting_item_count, m_starting_item_count, m_starting_item_count),
            new PieceCount(m_starting_item_count, m_starting_item_count, m_starting_item_count, m_starting_item_count),
            new PieceCount(m_starting_item_count, m_starting_item_count, m_starting_item_count, m_starting_item_count),
            new PieceCount(m_starting_item_count, m_starting_item_count, m_starting_item_count, m_starting_item_count),
        };

        List <Card>[] distributedCards = new List <Card>[4] {
            new List <Card>(), new List <Card>(), new List <Card>(), new List <Card>()
        };

        List <Card> remainingCards = new List <Card>(m_cards);

        Utility.Shuffle(remainingCards);

        // Each player takes turns getting 1 card that concerns themselves
        for (int turn = 0; turn < m_cardsForSelf; turn++)
        {
            for (int player = 0; player < 4; player++)
            {
                // Take cards that concern self and that both players have the pieces for
                int cardIndex = 0;
                while (true)
                {
                    if (((int)remainingCards[cardIndex].m_playerA == player || (int)remainingCards[cardIndex].m_playerB == player) &&
                        HaveEnoughPiecesForCard(pieceCounts, remainingCards[cardIndex]))
                    {
                        break;
                    }

                    cardIndex++;
                    if (cardIndex >= remainingCards.Count)
                    {
                        // There is no card that fits the requirements
                        throw new DistributionFailureException();
                    }
                }

                ProcessCardRequirements(pieceCounts, remainingCards[cardIndex]);
                distributedCards[player].Add(remainingCards[cardIndex]);
                remainingCards.RemoveAt(cardIndex);
            }
        }

        for (int turn = 0; turn < m_cardsForOthers; turn++)
        {
            for (int player = 0; player < 4; player++)
            {
                // Take cards that DON'T concern self and that both players have the pieces for
                int cardIndex = 0;
                while (true)
                {
                    if ((int)remainingCards[cardIndex].m_playerA != player && (int)remainingCards[cardIndex].m_playerB != player &&
                        HaveEnoughPiecesForCard(pieceCounts, remainingCards[cardIndex]))
                    {
                        break;
                    }

                    cardIndex++;
                    if (cardIndex >= remainingCards.Count)
                    {
                        // There is no card that fits the requirements
                        throw new DistributionFailureException();
                    }
                }

                ProcessCardRequirements(pieceCounts, remainingCards[cardIndex]);
                distributedCards[player].Add(remainingCards[cardIndex]);
                remainingCards.RemoveAt(cardIndex);
            }
        }

        // Sort cards for easy distribution
        for (int player = 0; player < 4; player++)
        {
            distributedCards[player].Sort(CompareCards);
        }

        return(distributedCards);
    }