[Script] Weighted Select Random

Party-approved future science plus handbooks for the revolution
Post Reply
darkChozo
Host
Posts: 206
Joined: Fri Aug 14, 2015 12:48 pm

[Script] Weighted Select Random

Post by darkChozo » Fri Jan 29, 2016 6:34 pm

EDIT: I'm dumb and didn't realize that BIS_fnc_selectRandomWeighted is a thing. Still, my script has several advantages, including the ability to set weights greater than 1 and (IMO) a better format for the input array. Consider this a bit of a tutorial/launching point for your own scripts in any case.

=================

This is a little script that I've found is quite useful in creating dynamic spawn scripts. Basically, it's a weighted version of BIS_fnc_selectRandom. Instead of selecting a random item from a list of items, it selects a random item from an adhoc map of weights to items, with higher-weighted items being more likely to be selected.

Example usage:

Code: Select all

weightedSelectRandom = compileFinal preprocessFileLineNumbers "weightedSelectRandom.sqf";
[[1,item0],[1,item1],[2,item2]] call weightedSelectRandom;
This is functionally the same as calling:

Code: Select all

[item0,item1,item2,item2] call BIS_fnc_selectRandom;
So, how is this useful? Let's say you want to randomly spawn a group of infantry. You want the groups you spawn to mostly be riflemen, but you don't want to hardcode your group composition. You could do something like this:

Code: Select all

_group = createGroup west;
for "_i" from 1 to 6 do {
  _class = [[4,"B_Soldier_G"],[1,"B_soldier_AR_F"],[1,"B_soldier_LAT_F"],[.2,"B_medic_F"],[.1,"B_Sharpshooter_F"]] call weightedSelectRandom;
  _group createUnit [_class,getMarkerPos "spawn",_group,[],0,"FORM"];
};
On average, this would spawn 6-man groups composed of 4 riflemen, 1 autorifleman, 1 AT rifleman, with occasional groups spawning with a medic or a sharpshooter. This same concept can be extended to group spawns as well; for example, you could have a spawn script that mostly spawns infantry teams but occasionally spawns MRAPs or armor instead. The reinforcements script for Upward Mobility and the dynamic spawn script for (the as-of-yet unplayed) Convoy are both written using this approach.

The script:
Pastebin

Code: Select all

/*
 * Randomly select an item from a weighted array. Array should be in the following format:
 * [[weight0,item0],[weight1,item1]...]. Items with a higher weight are more likely to be
 * chosen; for the array [[1,item0],[2,item1]], there is a 1/3 chance of choosing item0
 * and a 2/3 chance of choosing item1.
 *
 * Example usage: [[1,item0],[1,item1],[2,item2]] call weightedSelectRandom;
 */
 
_sum = 0;
{ _sum = _sum + (_x select 0); } forEach _this;

_roll = random _sum;

_sum = 0;
{
    _sum = _sum + (_x select 0);
    if (_roll < _sum) exitWith {_x select 1};
} forEach _this;

Post Reply