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.

Constructor

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).

Forced Elements

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

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.

Functions

addMany

<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);`

addArray

<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.

merge

<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

add

<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.

contains

<WeightedContainer>.contains( _item )
// _item can be any data type

Returns true if _item is an element of the Weighted Container.
Returns false otherwise.

remove

<WeightedContainer>.remove( _item )
// _item can be any data type

Removes _item from the Weighted Container

getProbability

<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.

getWeight

<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.

setWeight

<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.

apply

<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.

map

<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.

filter

<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.

clear

<WeightedContainer>.clear()

Clears the Weighted Container.

max

<WeightedContainer>.max()

Returns the item with the highest weight, excluding forced items.

rand

<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.

roll

<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.

rollChance

<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.

toArray

<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.

len

<WeightedContainer>.len()

Returns an integer which is the number of items in this Weighted Container.

Other Features

  • Can be cloned via the squirrel clone keyword.
  • Supports foreach (item, weight in WeightedContainer) iteration.
  • Has onSerialize( _out ) and onDeserialize( _in ) functions for easy save/load. Note: These functions only support the data type string for "items" in the WeightedContainer.

Example

// 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
⚠️ **GitHub.com Fallback** ⚠️