weighted container - MSUTeam/MSU GitHub Wiki
File Path: msu/classes/weighted_container.nut
A Weighted Container is an easy way to store elements with assigned weights, and then randomly select an element from the container.
local weightedContainer = ::MSU.Class.WeightedContainer( _array = null );
// _array is an arrayIf _array is null, the Weighted Container initializes empty,
if it isn't, after initialization the Weighted Container calls
this.addArray(_array).
Any elements with negative weights are considered forced. Forced elements are elements that have effectively infinite weight. If any forced element is present, no non-forced elements can be rolled. Forced elements are considered as having equal weight to each other.
Excluded elements are those passed as an array for a function to be completely excluded from the list of elements it considers. Their weight is effectively set to 0 for the lifetime of the function.
<WeightedContainer>.addMany( _weight, _array );
// _weight is an integer or float
// _array is an arrayCalls this.add(_weight, element) for each element in the array, and returns the WeightedContainer at the end. Therefore, it can be used as a pseudo-constructor:
local myContainer = ::MSU.Class.WeightedContainer().addMany(1, myArray);`<WeightedContainer>.addArray( _array );
// _array is an array of length 2 arraysCalls this.add(element[1], element[0]) on each element in the array.
Therefore, each element in _array must be a length 2 array whose first element
is the weight and the second element the item to be stored.
<WeightedContainer>.merge( _otherContainer );
// _otherContainer is an instance of WeightedContainerCalls this.add(item, weight) on each item in _otherContainer to add it to this container
<WeightedContainer>.add( _item, _weight = 1 )
// _item can be any data type
// _weight is an integer or floatIf _item is an element of the Weighted Container,
increases its weight by _weight.
Adds _item to the container with weight _weight otherwise.
A negative weight makes an element forced.
<WeightedContainer>.contains( _item )
// _item can be any data typeReturns true if _item is an element of the Weighted Container.
Returns false otherwise.
<WeightedContainer>.remove( _item )
// _item can be any data typeRemoves _item from the Weighted Container
<WeightedContainer>.getProbability( _item, _exclude = null )
// _item is an element in the Weighted Container
// _exclude is an arrayReturns the float probability of rolling _item when calling roll().
_exclude is an array of elements in the Weighted Container that should be excluded from a roll.
Throws ::MSU.Exception.KeyNotFound if _item doesn't exist
in the Weighted Container.
<WeightedContainer>.getWeight( _item )
// _item is an elemnt of the Weighted ContainerReturns the weight of _item in the container.
Throws ::MSU.Exception.KeyNotFound if _item doesn't exist
in the Weighted Container.
<WeightedContainer>.setWeight( _item, _weight )
// _item is an element of the Weighted Container
// _weight is an integer or floatSets the weight of _item to _weight.
Throws ::MSU.Exception.KeyNotFound if _item doesn't exist
in the Weighted Container.
<WeightedContainer>.apply( _function )
// _function is a function with two arguments: _item, _weight
// _function must return the new weight for _item
// _item is an element of the Weighted Container
// _weight is its corresponding weightIterates over all the elements of the Weighted Container
and calls _function on them. For each iteration the function is passed the item as its first parameter and its corresponding weight as the second parameter. _function must return the new weight for the item, which is then set as the item's weight.
<WeightedContainer>.map( _function )
// _function is a function with two arguments: _item, _weight
// _function must return a length 2 array with [ weight, item ] as its elements
// _item is an element of the Weighted Container
// _weight is its corresponding weightIterates over all the elements of the Weighted Container
and adds the the return value of calling _function on them
to a new Weighted Container which it then returns. To accomplish this, _function must return an array of length 2 of the format [weight, item] where item is the new item that will be added to the returned Weighted Container and weight is its weight.
<WeightedContainer>.filter( _function )
// _function is a function with two arguments: _item, _weight
// _function must return a Boolean
// _item is an element of the Weighted Container
// _weight is its corresponding weightIterates over all the elements of the Weighted Container
and adds them to a new Weighted Container if _function returns true.
It returns this new Weighted Container.
<WeightedContainer>.clear()Clears the Weighted Container.
<WeightedContainer>.max()Returns the item with the highest weight, excluding forced items.
<WeightedContainer>.rand( _exclude = null )
// _exclude is an arrayReturns a completely random (ignoring weight) element from the container,
while ignoring elements present in the _exclude array.
<WeightedContainer>.roll( _exclude = null )
// _exclude is an arrayReturns a random (biased by weight) element from the array,
with _exclude containing excluded items
and forced items being taken into account.
<WeightedContainer>.rollChance( _chance, _exclude = null )
// _chance is an integer
// _exclude is an arrayReturns <WeightedContainer>.roll(_exclude) if a random number between 1 and 100
is less than or equal to _chance, otherwise returns null.
<WeightedContainer>.toArray( _itemsOnly = true )
// _itemsOnly is a BooleanReturns an array. If _itemsOnly is true then the array only contains the
items stored in the weighted container. If _itemsOnly is false then the array
contains arrays of length 2 where the first element is the item's weight and the
second element is the item.
<WeightedContainer>.len()Returns an integer which is the number of items in this Weighted Container.
- Can be cloned via the squirrel
clonekeyword. - Supports
foreach (item, weight in WeightedContainer)iteration. - Has
onSerialize( _out )andonDeserialize( _in )functions for easy save/load. Note: These functions only support the data typestringfor "items" in the WeightedContainer.
// if you have an array of items and want to create a
// weighted container with those items with equal weight:
local weightedContainer = ::MSU.Class.WeightedContainer().addMany(1, myArray); // will add all elements of myArray to the container with a weight of 1
// alternatively, you can create a weighted container by passing an array
// of len 2 arrays with weight and item:
local weightedContainer = ::MSU.Class.WeightedContainer([
[1, "String Weight1"],
[4, "String Weight4"],
[10, "String Weight10"],
[1, 2] // Integer weight 1
]);
weightedContainer.add("New String Weight1");
weightedContainer.addArray([
[3, 4], // Integer weight 3
[10, {}] // Table weight 10
]);
local randomValue = weightedContainer.roll();
local maybeRandomValue = weightedContainer.rollChance(50);
// has a 50% chance to be null