示例#1
0
    /// <summary>
    /// Computes a partial hand distribution of the specified player,
    /// for an assumed world state and the observation of which card they played.
    /// </summary>
    /// <param name="PlayedCardIndex">The index of the card that was played by the opponent.</param>
    /// <param name="HandIndex">The index of the card that the other player is assumed to have in their hand.</param>
    /// <param name="OutDistribution">A reference to a probability distribution that containts return values.</param>
    protected void UpdatePartialHandDistribution(int PlayedCardIndex, int PlayerHand, ref Distribution1D OutDistribution)
    {
        // Don't continue if priori probability is zero
        float PrioriProbability = SingleOpponentHandDistribution[PlayerHand];

        if (PrioriProbability <= 0)
        {
            return;
        }
        // Make a copy of the unaccounted card counters and update it with the "virtually" accounted-for cards
        Array.Copy(CountUnaccountedForCards, 1, virtualRemainingCards, 0, CARD_VECTOR_LENGTH);
        if (--virtualRemainingCards[PlayerHand] < 0)
        {
            return; // If a counter goes below zero, this is an impossible case, so return without an update
        }
        // Prepare computation
        int remainingDeckSize = AIUtil.SumUpArray(virtualRemainingCards);

        Debug.Assert(remainingDeckSize > 0);
        // Now loop through each deck card and see if the card that was played could have been played from hand or from deck
        for (int dc = 0; dc < CARD_VECTOR_LENGTH; dc++)
        {
            if (virtualRemainingCards[dc] > 0 && (PlayedCardIndex == PlayerHand || PlayedCardIndex == dc))
            {
                // Compute which card the player has left in their hand, given PlayedCardIndex
                int otherCard = (PlayedCardIndex == PlayerHand) ? dc : PlayerHand;
                // Calculate the joint probability of such play
                OutDistribution[otherCard] += PrioriProbability * virtualRemainingCards[dc] / remainingDeckSize *
                                              PosterioriPerceptor.LikelihoodOfPlay[PlayedCardIndex + 1, otherCard + 1];
            }
        }
    }
示例#2
0
 // Convenience function for easier deck distribution calculation
 // Note that because it is CUMULATIVE, DeckDistributionBuffer contains intermediary results and may not be cleared!
 protected void CumulativeUpdateDeckDistribution(float Probability, int[] RemainingCards, ref Distribution1D DeckDistributionBuffer)
 {
     Debug.Assert(RemainingCards.Length == CARD_VECTOR_LENGTH);
     Debug.Assert(DeckDistributionBuffer.Length == CARD_VECTOR_LENGTH);
     if (Probability > 0)
     {
         int sum = AIUtil.SumUpArray(RemainingCards);
         if (sum > 0)
         {
             for (int i = 0; i < CARD_VECTOR_LENGTH; i++)
             {
                 if (RemainingCards[i] > 0)
                 {
                     DeckDistributionBuffer[i] += Probability * RemainingCards[i] / sum;
                 }
             }
         }
     }
 }
示例#3
0
    /// <summary>
    /// Computes a partial hand distribution of the specified player,
    /// for an assumed world state and the observation of which card they played.
    /// </summary>
    /// <param name="TurnData">Complete data of the turn being analyzed.</param>
    /// <param name="Hand0">The index of the card the first of the three remaining opponents is asssumed to hold.</param>
    /// <param name="Hand1">The index of the card the second of the three remaining opponents is asssumed to hold.</param>
    /// <param name="Hand2">The index of the card the third of the three remaining opponents is asssumed to hold.</param>
    /// <param name="OutDistribution">A reference to a probability distribution that containts return values.</param>
    protected void UpdatePartialHandDistribution(MoveData TurnData, int Hand0, int Hand1, int Hand2, ref Distribution3D OutDistribution)
    {
        // Don't continue if priori probability is zero
        float PrioriProbability = ThreeOpponentsHandsDistribution[Hand0, Hand1, Hand2];

        if (PrioriProbability <= 0)
        {
            return;
        }
        // Make a copy of the unaccounted card counters and update it with the "virtually" accounted-for cards
        Array.Copy(CountUnaccountedForCards, 1, virtualRemainingCards, 0, CARD_VECTOR_LENGTH);
        if (--virtualRemainingCards[Hand0] < 0 || --virtualRemainingCards[Hand1] < 0 || --virtualRemainingCards[Hand2] < 0)
        {
            return; // If a counter goes below zero, this is an impossible case, so return without an update
        }
        // Parse the turn data
        int PlayerIndex     = GetHiddenHandIndex(TurnData.Player.SittingOrder),
            PlayedCardIndex = TurnData.Card.Value - 1,
            TargetIndex     = (TurnData.Target == null || TurnData.Target.SittingOrder == MySittingOrder) ? -1 : GetHiddenHandIndex(TurnData.Target.SittingOrder);

        // Determine which card in the current data belongs to PlayerIndex
        int[] idx        = new int[] { Hand0, Hand1, Hand2 };
        int   playerHand = idx[PlayerIndex],
              targetHand = TargetIndex != -1 ? idx[TargetIndex] : -1;
        // Prepare computation
        int remainingDeckSize = AIUtil.SumUpArray(virtualRemainingCards);

        Debug.Assert(remainingDeckSize > 0);
        // Now loop through each deck card and see if the card that was played could have been played from hand or from deck
        for (int dc = 0; dc < CARD_VECTOR_LENGTH; dc++)
        {
            if (virtualRemainingCards[dc] > 0 && (PlayedCardIndex == playerHand || PlayedCardIndex == dc))
            {
                // Compute which card the player has left in their hand, given PlayedCardIndex
                int otherCard = (PlayedCardIndex == playerHand) ? dc : playerHand;
                // Prepare the index values for the update
                idx[PlayerIndex] = otherCard;
                // Calculate the joint probability of such play and increment the output array
                OutDistribution[idx[0], idx[1], idx[2]] += PrioriProbability * virtualRemainingCards[dc] / remainingDeckSize
                                                           * GetLikelihoodOfPlay(TurnData, otherCard + 1, targetHand + 1);
            }
        }
    }
示例#4
0
    /// <summary>
    /// Computes a partial hand distribution of the specified player's new hand after being targeted by the Prince,
    /// for an assumed world state and the observation of which card they previously discarded.
    /// </summary>
    /// <param name="PlayerIndex">Index of the player for whom the computation is performed.</param>
    /// <param name="Hand0">The index of the card the first of the three remaining opponents is asssumed to hold.</param>
    /// <param name="Hand1">The index of the card the second of the three remaining opponents is asssumed to hold.</param>
    /// <param name="Hand2">The index of the card the third of the three remaining opponents is asssumed to hold.</param>
    /// <param name="DiscardedIndex">The observed index of the card that the player had discarded.</param>
    /// <param name="OutDistribution">A reference to a probability distribution that containts return values.</param>
    protected void PrinceDiscardAndDrawPartialUpdate(int PlayerIndex, int Hand0, int Hand1, int Hand2, int DiscardedIndex, ref Distribution3D OutDistribution)
    {
        // Don't continue if priori probability is zero
        float PrioriProbability = ThreeOpponentsHandsDistribution[Hand0, Hand1, Hand2];

        if (PrioriProbability <= 0)
        {
            return;
        }
        // Determine which card in the current data belongs to PlayerIndex
        int[] idx        = new int[] { Hand0, Hand1, Hand2 };
        int   playerHand = idx[PlayerIndex];

        if (playerHand != DiscardedIndex)
        {
            return;
        }
        // Make a copy of the unaccounted card counters and update it with the "virtually" accounted-for cards
        Array.Copy(CountUnaccountedForCards, 1, virtualRemainingCards, 0, CARD_VECTOR_LENGTH);
        if (--virtualRemainingCards[Hand0] < 0 || --virtualRemainingCards[Hand1] < 0 || --virtualRemainingCards[Hand2] < 0)
        {
            return; // If a counter goes below zero, this is an impossible case, so return without an update
        }
        // Prepare computation
        int remainingDeckSize = AIUtil.SumUpArray(virtualRemainingCards);

        if (remainingDeckSize < 1)
        {
            return; // The game is over, anyway.
        }
        Debug.Assert(remainingDeckSize > 0);
        // Now loop through each deck card and see if the card that was played could have been played from hand or from deck
        for (int dc = 0; dc < CARD_VECTOR_LENGTH; dc++)
        {
            if (virtualRemainingCards[dc] > 0)
            {
                // Calculate the joint probability of such play and increment the output array
                idx[PlayerIndex] = dc;
                OutDistribution[idx[0], idx[1], idx[2]] += PrioriProbability * virtualRemainingCards[dc] / remainingDeckSize;
            }
        }
    }