private void CalculateOptions(AbstractAIBrain utilityAiBrain) { if (utilityAiBrain == null) { return; } // Setup Contexts utilityAiBrain.GetNodes <EntryNode>().ForEach(node => node.SetContext(this)); utilityAiBrain.GetNodes <ActionNode>().ForEach(node => node.SetContext(this)); // Add the brain to the option dictionary if (Options.ContainsKey(utilityAiBrain)) { Options[utilityAiBrain].Clear(); } else { Options.Add(utilityAiBrain, new List <AIOption>()); } utilityAiBrain.GetNodes <OptionNode>().ForEach(node => Options[utilityAiBrain] .AddRange(node.GetOptions())); // Return if no option found if (Options[utilityAiBrain].Count == 0) { return; } // Calculate Probability foreach (AIOption aiOption in Options[utilityAiBrain]) { aiOption.Probability = aiOption.Utility / Options[utilityAiBrain] .Where(option => option.Weight == aiOption.Weight) .Sum(option => option.Utility); } // Order by Weight then Utility Options[utilityAiBrain] = Options[utilityAiBrain].OrderByDescending(option => option.Weight).ThenByDescending(option => option.Utility).ToList(); }
protected AIOption ChooseOption() { if (UtilityAiBrain == null) { return(null); } UtilityAiBrain.GetNodes <EntryNode>().ForEach(node => node.SetContext(this)); UtilityAiBrain.GetNodes <ActionNode>().ForEach(node => node.SetContext(this)); // Fill the Ranked Options Options = new List <AIOption>(); UtilityAiBrain.GetNodes <OptionNode>().ForEach(node => Options.AddRange(node.GetOptions())); // Remove ImpossibleDecisionValue Ranks Options.RemoveAll(option => option.Rank <= 0f); if (Options.Count == 0) { return(null); } // Get max Rank int maxRank = Options.Max(option => option.Rank); for (int i = maxRank; i > 0; i--) { List <AIOption> options = Options.FindAll(utility => utility.Rank == i); if (options.Count == 0 || options.Sum(utility => utility.Utility) <= 0) { continue; } // Calculating Weight options.ForEach(dualUtility => dualUtility.Weight = dualUtility.Utility / Options.Sum(utility => utility.Utility)); // Rolling probability on weighted random LastProbabilityResult = Random.Range(0f, 1f); float weightSum = 0f; foreach (AIOption dualUtility in options) { weightSum += dualUtility.Weight; if (weightSum >= LastProbabilityResult) { return(dualUtility); } } } return(null); }