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 array
If _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 array
Calls 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 arrays
Calls 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 WeightedContainer
Calls 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 float
If _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 type
Returns true
if _item
is an element of the Weighted Container.
Returns false
otherwise.
<WeightedContainer>.remove( _item )
// _item can be any data type
Removes _item
from the Weighted Container
<WeightedContainer>.getProbability( _item, _exclude = null )
// _item is an element in the Weighted Container
// _exclude is an array
Returns 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 Container
Returns 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 float
Sets 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 weight
Iterates 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 weight
Iterates 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 weight
Iterates 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 array
Returns a completely random (ignoring weight) element from the container,
while ignoring elements present in the _exclude
array.
<WeightedContainer>.roll( _exclude = null )
// _exclude is an array
Returns 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 array
Returns <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 Boolean
Returns 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
clone
keyword. - Supports
foreach (item, weight in WeightedContainer)
iteration. - Has
onSerialize( _out )
andonDeserialize( _in )
functions for easy save/load. Note: These functions only support the data typestring
for "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