Skip to content

Instantly share code, notes, and snippets.

@MightyPrinny
Created January 24, 2020 06:43
Show Gist options
  • Save MightyPrinny/342ca512ad8926a98e03c04020b22448 to your computer and use it in GitHub Desktop.
Save MightyPrinny/342ca512ad8926a98e03c04020b22448 to your computer and use it in GitHub Desktop.
Chooses values from an array using a probabilities array
/// <summary>
///Returns a random object from the array with probabilities
///</summary>
/// <param name="prob">the probability of being chosen for each value in the array, their sum must be <= 1</param>
public static T ChooseWithProbabilities<T>(float[] prob,params T[] array)
{
float rn = RNG.Randf();
int len = array.Length;
float[][] intervals = new float[len][];
if (len != prob.Length || len == 0)
{
return default;
}
float total = 0;
float intervalStart = 0;
for (int i = prob.Length - 1; i >= 0; --i)
{
intervals[i] = new float[2];
intervals[i][0] = intervalStart;
intervals[i][1] = intervalStart + prob[i];
total += prob[i];
intervalStart += intervals[i][1];
}
if (total > 1 && (Mathf.Abs(total - 1) > 0.01f))
{
GD.PrintErr("Bad probabilities array");
return default;
}
for (int i = intervals.Length - 1; i >= 0; --i)
{
if (rn >= intervals[i][0] && rn <= intervals[i][1])
{
return array[i];
}
}
return default;
}
@MightyPrinny
Copy link
Author

Not unit tested, used in godot engine, the intervals could be stored in a struct to play nicer with the GC, but I wasn't calling it every frame so I just used arrays.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment