protected void UpdateStatisticsForPlayer(int SittingOrder, float[] ActualDeckDistribution, int DeckCardsLeft) { AIGenericPerceptor Perceptor = Perceptors[SittingOrder]; // Calculate the deck MSE float[] EstimatedDeckDistribution = Perceptor.GetCardProbabilitiesInDeck(); float nextDeckMSE = AIUtil.GetMeanSquaredError(ActualDeckDistribution, EstimatedDeckDistribution); float nextDeckXEE = AIUtil.GetCrossEntropyError(ActualDeckDistribution, EstimatedDeckDistribution); // Calculate the card adversary distribution for other players float nextAdversaryHandMSE = 0, nextAdversaryHandXEE = 0; Vector3 nextAdversaryHandMLC = Vector3.zero; float[] ActualHandDistribution = new float[CardController.VALUE_PRINCESS + 1], EstimatedHandDistribution; int countHandsChecked = 0; for (int p = 0; p < Players.Length; p++) { if (p != SittingOrder && !Players[p].KnockedOut) { // Simulate the target player's hand distribution (perfect certainty) Array.Clear(ActualHandDistribution, 0, ActualHandDistribution.Length); ActualHandDistribution[Players[p].GetHand().Value] = 1f; // Get MSE for this distribution EstimatedHandDistribution = Perceptor.GetCardProbabilitiesInHand(Players[p]); nextAdversaryHandMSE += AIUtil.GetMeanSquaredError(ActualHandDistribution, EstimatedHandDistribution); nextAdversaryHandXEE += AIUtil.GetCrossEntropyError(ActualHandDistribution, EstimatedHandDistribution); nextAdversaryHandMLC += AIUtil.GetMostLikelyCardError(EstimatedHandDistribution, Players[p].GetHand().Value); countHandsChecked += 1; } } // Update the statistics for this perceptor class if (countHandsChecked > 0) { nextAdversaryHandMSE /= countHandsChecked; nextAdversaryHandMLC /= countHandsChecked; PerceptorStats[PerceptorClassNames[SittingOrder]].AppendStatistics(nextDeckMSE, nextDeckXEE, DeckCardsLeft, nextAdversaryHandMSE, nextAdversaryHandXEE, nextAdversaryHandMLC, countHandsChecked); } }