Jump to content
Sign in to follow this  
thecoolsideofthepillow

When to use Random and when to use BIS_fnc_SelectRandom?

Recommended Posts

I am going to need to make some random selections for my mission, and I have not really tried to do it before. I am thinking it should be rather straight forward, but there are two commands I can use to make a random selection:

Random, which seems to only be a random number chosen between the two given numbers when calling the commands, and BIS_fnc_SelectRandom, which selects an item from an array.

Since I would need to declare an array or set of variables to use either, does it really matter which one I use? Is one faster than another?

I could essentially do the same thing in two fashions, though I am not sure if they are good methods in either case.

First, using "Random" I write 4 if statements that do something based on what variable is chosen by the random command:

One = if (condition) then {code};
Two = if (condition) then {code};
Three = if (condition) then {code};
Four = if (condition) then {code};

Second, I could just have my variables be script file names in an array and use the BIS_fnc_SelectRandom to pull one at random:

 _array = [script1, Script2, Script3, Script4] call BIS_fnc_SelectRandom

Obviously, the second way takes only a single line, but still requires 4 scripts. The first method only really requires a single script and 4 lines.

At the very least: Am I even using them correctly? I don't want to start writing a bunch of code only to have it turn out to be malformed or used incorrectly.

Share this post


Link to post
Share on other sites

Instead of all the if statements I would use a switch:

_rndNum = floor(random(4));

switch (_rndNum) do
{
case 0: {};
case 1: {};
case 2: {};
case 3: {};
default {};
};

Share this post


Link to post
Share on other sites

I recommend using it as an error catch so you know if something doesn't go right, or you could just choose one of your scripts to be the default, so whatever you are trying to do will defieently happen:

//error example, will send to the rpt log
default {diag_log "Error in switch in scriptName!!!!!"};

//defaulted script call
default {0 = [] execVM "myDefaultScript.sqf"};

Share this post


Link to post
Share on other sites

I am having an odd problem.

If I put this block of code into an .SQF file and call it from my Spawn AI's expression line with execVM, nothing happens.

_WSpawner = _this select 0;
{
_rndLoadout = floor(random(4)); 
switch (_rndLoadout) do {
	case 0: {[_x, missionconfigfile >> "CfgRespawnInventory" >> "WSupport"] call BIS_fnc_loadInventory;};
	case 1: {[_x, missionconfigfile >> "CfgRespawnInventory" >> "WEngineer"] call BIS_fnc_loadInventory;};
	case 2: {[_x, missionconfigfile >> "CfgRespawnInventory" >> "WAssault"] call BIS_fnc_loadInventory;};
	case 3: {[_x, missionconfigfile >> "CfgRespawnInventory" >> "WRecon"] call BIS_fnc_loadInventory;};
	default {systemChat "I AM ERROR"};
};
} forEach units _WSpawner;

However, if I put that same block directly into the expression field for the Spawn AI Module, it works. I think it might have something to do with the use of _this, but I am not sure. _this should be an array given by the module itself, but the execVM command also uses _this for something else. I only think this because if I put a hint or something at the end of the script, it does get executed so the script itself is working, it just isn't getting the right variable to produce the desired effects.

Share this post


Link to post
Share on other sites

_this is always just the parameters passed to the code. Like so:

player spawn {
   systemChat str(_this);
};

In that example, _this is whatever object was returned by the player command. So you need to pass whatever _WSpawner should be via the execVM command (and since it's _this select 0 you need to put it in an array).

Share this post


Link to post
Share on other sites

So, basically, putting this line in the expression field should make my script function:

_Array = [_this]; nul = [_Array] execVM "script.sqf";

?

Edited by TheCoolSideofthePillow

Share this post


Link to post
Share on other sites

In your case you actually only need to do.

_this execVM "script.sqf";

(Since you said it works directly from the expression field then it suggests whatever parameters are being passed to that field are already in an array). So you're essentially just passing the parameters down to the script directly.

Share this post


Link to post
Share on other sites

{
       [_x, missionconfigfile >> "CfgRespawnInventory" >> (["WSupport", "WEngineer", "WAssault", "WRecon"] call BIS_fnc_SelectRandom)] call BIS_fnc_loadInventory;
} forEach units _WSpawner;

is also viable in sqf, and I think its pretty readable.

Share this post


Link to post
Share on other sites
{
       [_x, missionconfigfile >> "CfgRespawnInventory" >> (["WSupport", "WEngineer", "WAssault", "WRecon"] call BIS_fnc_SelectRandom)] call BIS_fnc_loadInventory;
} forEach units _WSpawner;

is also viable in sqf, and I think its pretty readable.

Ooooh Nice. I didn't know I could use all the classes on a single line like that. The documentation for these newer functions isn't all there yet. I'm amazed how some of you guys even know this stuff.

Share this post


Link to post
Share on other sites

It needs string, theoretically the function returns string, the rest is simple paste.

Turn on script errors and start to abuse the system, you'll learn a lot in 2000 hours. :-)

Share this post


Link to post
Share on other sites
It needs string, theoretically the function returns string, the rest is simple paste.

Turn on script errors and start to abuse the system, you'll learn a lot in 2000 hours. :-)

^ this

you learn alot after banging your head against a land_stonewall_f in frustration for 2000+ hours.

With respect to the OP:

I would take KKs advice and simply avoid BIS_fnc_selectRandom. It does the job, but there is no need. Some alternatives:

_array = ['Cat','Dog','Sloth'];
_result = _array select (floor (random (count _array)));

/* Works the same as: */

_result = ['Cat','Dog','Sloth'] select (floor (random (count ['Cat','Dog','Sloth'])));

/* works the same as: */

_result = ['Cat','Dog','Sloth'] call BIS_fnc_selectRandom;

Edited by MDCCLXXVI

Share this post


Link to post
Share on other sites
^ this

you learn alot after banging your head against a land_stonewall_f in frustration for 2000+ hours.

With respect to the OP:

I would take KKs advice and simply avoid BIS_fnc_selectRandom. It does the job, but there is no need. Some alternatives:

_array = ['Cat','Dog','Sloth'];
_result = _array select (floor (random (count _array)));

/* Works the same as: */

_result = ['Cat','Dog','Sloth'] select (floor (random (count ['Cat','Dog','Sloth'])));

/* works the same as: */

_result = ['Cat','Dog','Sloth'] call BIS_fnc_selectRandom;

Just to point it out, you can write "_array select floor random count _array" just like that without all these parantheses. Makes it a bit better readable and writable in my opinion.

Share this post


Link to post
Share on other sites

this is one way to use the bis_fnc_selectrandom.

_array = [1,2,3,5];

_select = _array call BIS_fnc_Selectrandom;

hint format ["Random: %1",_select];

Share this post


Link to post
Share on other sites
Is one faster than another?

technically the function is faster than the count command.

arrayTestReturn = [1,2,3,5] call BIS_fnc_Selectrandom;
hint format ["Random: %1",arrayTestReturn]; 

0.0417 ms

arrayTestReturn = [1,2,3,5,2,3,5,2,3,5,2,3,5,2,3,5,2,3,5,2,3,5,2,3,5,2,3,5,2,3,5,2,3,5,2,3,5,2,3,5,2,3,5,2,3,5,2,3,5,2,3,5] call BIS_fnc_Selectrandom;
hint format ["Random: %1",arrayTestReturn];

0.0485 ms

arrayTestReturn = [1,2,3,5] select (floor (random (count [1,2,3,5])));
hint format ["Random: %1",arrayTestReturn];

0.0502 ms

arrayTestReturn = [1,2,3,5,2,3,5,2,3,5,2,3,5,2,3,5,2,3,5,2,3,5,2,3,5,2,3,5,2,3,5,2,3,5,2,3,5,2,3,5,2,3,5,2,3,5,2,3,5,2,3,5] select (floor (random (count [1,2,3,5,2,3,5,2,3,5,2,3,5,2,3,5,2,3,5,2,3,5,2,3,5,2,3,5,2,3,5,2,3,5,2,3,5,2,3,5,2,3,5,2,3,5,2,3,5,2,3,5])));
hint format ["Random: %1",arrayTestReturn];

0.0630 ms

the increase in larger arrays have more impact on the count command than the function.

you can test various code in the editor, press esc and insert code and click on the speedometer symbol left side under code box.

Share this post


Link to post
Share on other sites

I'm very skeptical of those claims. The function is using the count command itself as well as checking that the parameter is valid.

Share this post


Link to post
Share on other sites

Isn't the function literally "_array select floor random count _array" with BIS_fnc_Param and stuff? It's the scheduled environment difference that makes that little performance difference (if any noticeable).

Share this post


Link to post
Share on other sites

To clear it up, that's what BIS_fnc_selectRandom looks like inside:

[color=#FF8040][color=#006400][i]/************************************************************
   Random Select
   Author: Andrew Barron, rewritten by Warka, optimized by Karel Moricky

Parameters: array

This returns a randomly selected element from the passed array.

Example: [1,2,3] call BIS_fnc_selectRandom
Returns: 1, 2, or 3
************************************************************/[/i][/color]

[color=#191970][b]if[/b][/color] [color=#8B3E2F][b]([/b][/color][color=#191970][b]count[/b][/color] [color=#000000]_this[/color] [color=#8B3E2F][b]>[/b][/color] [color=#FF0000]0[/color][color=#8B3E2F][b])[/b][/color] [color=#191970][b]then[/b][/color] [color=#8B3E2F][b]{[/b][/color]
   [color=#000000]_this[/color] [color=#191970][b]select[/b][/color] [color=#8B3E2F][b]([/b][/color][color=#191970][b]floor[/b][/color] [color=#191970][b]random[/b][/color] [color=#8B3E2F][b]([/b][/color][color=#191970][b]count[/b][/color] [color=#000000]_this[/color][color=#8B3E2F][b])[/b][/color][color=#8B3E2F][b])[/b][/color][color=#8B3E2F][b];[/b][/color]
[color=#8B3E2F][b]}[/b][/color] [color=#191970][b]else[/b][/color] [color=#8B3E2F][b]{[/b][/color]
   [color=#8B3E2F][b][[/b][/color][color=#7A7A7A]"Array has no elements."[/color][color=#8B3E2F][b]][/b][/color] [color=#191970][b]call[/b][/color] bis_fnc_error[color=#8B3E2F][b];[/b][/color]
   [color=#000000]nil[/color]
[color=#8B3E2F][b]}[/b][/color][color=#8B3E2F][b];[/b][/color][/color]

Kudos to Killzone_Kid for his SQF to BBCode Converter.

So yes, it literally uses "_this select floor random count _this" and yes, calling the function is (obviously) slightly slower than doing the random select "manually", especially because the array needlessly gets counted twice in there.

Edited by Heeeere's Johnny!

Share this post


Link to post
Share on other sites

Please sign in to comment

You will be able to leave a comment after signing in



Sign In Now
Sign in to follow this  

×