Larian Studios

Random() is not very random

Posted By: Windemere

Random() is not very random - 27/01/18 01:28 AM

I'm wondering if Larian or anyone else can answer how the call to Random() in Osiris gets seeded. Whenever I invoke this call in the editor, I seem to get the same result back test after test after test until suddenly it will finally change, and then stick again for a while. I just finished testing some story script where I use a modulo of 14 and out of about a dozen tests I got 0 for the result back the first 6 or 7 times and then it changed to 1 for the next 6 or 7. Is there any way to make this call generate more random results when testing in the editor? Even re-opening the project every time doesn't seem to help much.

Thanks.
Posted By: The Composer

Re: Random() is not very random - 27/01/18 01:34 AM

I don't know what in particular you're set out to do, but something that works well for me is the following. It decides one out of 14 different outcomes and it's quite random and fluid for me.

INIT

DB_DC_FTJIRandom(1);


KB

...
AND
DB_DC_FTJIRandom(_Chance)
AND
Random(14, _Ran)
AND
_Ran >= _Chance
...
Posted By: Windemere

Re: Random() is not very random - 27/01/18 01:45 AM

I'm doing something similar but like I said, the output value from Random repeats itself from one playtest to another multiple times in a row.
Posted By: The Composer

Re: Random() is not very random - 27/01/18 01:59 AM

Odd... Though I do remember having some sort of issue too. It's quite a while ago so the details are fuzzy at best, but I had some success when changing the output to strings. Absolutely no idea why, but it solved all my headaches at the time. Mysteries of the engine, right?



IF
TimerFinished("DCDouseBraziers")
AND
DB_DC_FTJIRandom(_Chance)
AND
Random(14, _Ran)
AND
_Ran >= _Chance
AND
IntegertoString(_Ran, _RanDisp)
THEN
NOT DB_DC_FTJIPunishment(_RanDisp);
DB_DC_FTJIPunishment(_RanDisp);
Proc_FTJI_Secret_Punishment();


(The fifth variant here as an example, since it's short)

PROC
Proc_FTJI_Secret_Punishment()
AND
DB_IsPlayer(_Player)
AND
DB_DC_FTJIPunishment("5")
AND
DB_DC_FTJI_ShroomsPuzzle(_FTJIShroom)
THEN
PlayEffect(_FTJIShroom, "RS3_FX_GP_Impacts_Arrow_PoisonCloud_01");
CreatePuddle(_FTJIShroom, "SurfacePoisonCloud", 80, 130, 60, 60, 0.5);
NOT DB_DC_FTJIPunishment("5");


Posted By: Windemere

Re: Random() is not very random - 27/01/18 02:16 AM

Here is the code in question, which just applies a random preset on the dummy character when testing in editor mode. I'll wrap some lines of interest in double asterisks to make them easier to find.

Code
INIT
DB_EditorMode_Presets(0, "Battlemage");
DB_EditorMode_Presets(1, "Cleric");
DB_EditorMode_Presets(2, "Conjurer");
DB_EditorMode_Presets(3, "Enchanter");
DB_EditorMode_Presets(4, "Fighter");
DB_EditorMode_Presets(5, "Inquisitor");
DB_EditorMode_Presets(6, "Knight");
DB_EditorMode_Presets(7, "Metamorph");
DB_EditorMode_Presets(8, "Ranger");
DB_EditorMode_Presets(9, "Rogue");
DB_EditorMode_Presets(10, "Shadowblade");
DB_EditorMode_Presets(11, "Wayfarer");
DB_EditorMode_Presets(12, "Witch");
DB_EditorMode_Presets(13, "Wizard");

IF
GameModeStarted("Campaign",1)
AND
DB_GLO_FirstLevelAfterCharacterCreation(_Level)
AND
DB_CharacterCreationTransitionInfo(_Level,_Trigger)
AND
**Random(14, (INTEGER)_Random)**
THEN
SetOnStage(S_GLO_CharacterCreationDummy_001_da072fe7-fdd5-42ae-9139-8bd4b9fca406,1);
CharacterMakePlayer(S_GLO_CharacterCreationDummy_001_da072fe7-fdd5-42ae-9139-8bd4b9fca406);
MakePlayerActive(S_GLO_CharacterCreationDummy_001_da072fe7-fdd5-42ae-9139-8bd4b9fca406);
DB_IsPlayer(S_GLO_CharacterCreationDummy_001_da072fe7-fdd5-42ae-9139-8bd4b9fca406);
SetFaction(S_GLO_CharacterCreationDummy_001_da072fe7-fdd5-42ae-9139-8bd4b9fca406, "Hero");
**ProcApplyEditorPreset(S_GLO_CharacterCreationDummy_001_da072fe7-fdd5-42ae-9139-8bd4b9fca406, _Random);**
ProcMovePartyToStart(S_GLO_CharacterCreationDummy_001_da072fe7-fdd5-42ae-9139-8bd4b9fca406,_Trigger);

PROC
ProcApplyEditorPreset((CHARACTERGUID)_Player, (INTEGER)_Index)
AND
DB_EditorMode_Presets(_Index, _Preset)
THEN
CharacterApplyPreset(_Player, _Preset);


And here are the test results. Between each run I completely re-open the project and starting level from scratch and have some additional actions noted on some of the other runs.

1st run
exec [DIV query] Random( 14, [out] (INTEGER)(undef value) )
Query returns: Random( 14, 4 )

2nd run same as before
exec [DIV query] Random( 14, [out] (INTEGER)(undef value) )
Query returns: Random( 14, 4 )

3rd run same as before
exec [DIV query] Random( 14, [out] (INTEGER)(undef value) )
Query returns: Random( 14, 4 )

4th run same as before
exec [DIV query] Random( 14, [out] (INTEGER)(undef value) )
Query returns: Random( 14, 4 )

**EXIT EDITOR and RESTART**

5th run same as before
exec [DIV query] Random( 14, [out] (INTEGER)(undef value) )
Query returns: Random( 14, 4 )

6th run same as before
exec [DIV query] Random( 14, [out] (INTEGER)(undef value) )
Query returns: Random( 14, 4 )

** Move some code order around and re-build the story **

7th run same as before
exec [DIV query] Random( 14, [out] (INTEGER)(undef value) )
Query returns: Random( 14, 4 )

** Open a different project and test it for a while **
** Open this project back up and test (no code changes) **

8th run finally changes!
exec [DIV query] Random( 14, [out] (INTEGER)(undef value) )
Query returns: Random( 14, 5 )

** Reload Project and Start **

9th run same as before
exec [DIV query] Random( 14, [out] (INTEGER)(undef value) )
Query returns: Random( 14, 5 )

** Open a different project and test it for a while **
** Open this project back up and test (no code changes) **

10th run same as before
exec [DIV query] Random( 14, [out] (INTEGER)(undef value) )
Query returns: Random( 14, 5 )

and so on ... ouch

Posted By: BloodyWorth

Re: Random() is not very random - 28/01/18 08:47 PM

One thing you can do to increase randomness is adding random simulated layers (I'm guessing this is what it is called in english, don't know the offical name sorry) like so:

Code
PROC
Rand_OneLayer((INTEGER)_maximum,(INTEGER)_rand)
AND
Random(_maximum,_rand1)
AND
DB_RandomShit1(_rand1,1)
AND
Random(_maximum,_rand2)
AND
DB_RandomShit1(_rand2,2)
AND
Random(_maximum,_rand3)
AND
DB_RandomShit1(_rand3,3)
AND
Random(_maximum,_rand4)
AND
DB_RandomShit1(_rand4,4)
AND
Random(4,_sel)
THEN
DB_RandomShit1(_rand,_sel);


This is just an exemple, you can make it "more random" by either increasing its "range" ex.: go all the way to DB_RandomShit(_rand100,100), or increasing its depth, where instead of calling the random function to get the random number, you call a proc just like this one, this way you'd be adding a "layer" to it, something like:

Code
PROC
Rand_TwoLayer((INTEGER)_maximum,_rand)
AND
Rand_OneLayer(_maximum,_rand1)
AND
DB_RandomShit2(_rand1,1)
AND
Rand_OneLayer(_maximum,_rand2)
AND
DB_RandomShit2(_rand2,2)
AND
Rand_OneLayer(_maximum,_rand3)
AND
DB_RandomShit2(_rand3,3)
AND
Rand_OneLayer(_maximum,_rand4)
AND
DB_RandomShit2(_rand4,4)
AND
Random(4,_sel)
THEN
DB_RandomShit2(_rand,_sel);


There are some other ways, but i'm not sure how real and integer conversions work on osiris, i do know that generating random numbers between 0 - 1 will have a better random value, i remember my teacher explained this in linear algebrae but i can't remember so take it with a grain of salt.

Hope it helps laugh
Posted By: Windemere

Re: Random() is not very random - 28/01/18 10:03 PM

Thanks, I understand how to make workarounds but I'd like some insight into the behavior as it is now. There aren't a bunch of unholy workarounds in Origins to make Random actually behave randomly, so I'm looking to see if there is something unique about running in editor mode with cached data hanging around somewhere, or if there is something else I'm not accounting for.
Posted By: Module 003

Re: Random() is not very random - 29/01/18 10:56 PM

I found Random() to behave strange as well.
Used it in a class mod, to get %chance to apply custom scripted status, and was always unhappy with result.

Sometimes it just returns same values for like 20 times in a row, and only after that start working.
Had to add some "controled RNG" to prevent it from returning same values (using DB_Counters) and make some additional treshods.
Was working with flat Integer numbers 1-100.

Donno why it is so buggy, but think that is just smth we have to deal with.
Posted By: Tinkerer

Re: Random() is not very random - 01/02/18 01:14 PM

The Osiris Random() call uses the standard C(++) library's "rand()" function. However, there are a few places in the engine where the random seed gets reset, and maybe some external libraries also do this. I'll look into changing it into something that is independent of external influences.
Posted By: Windemere

Re: Random() is not very random - 01/02/18 03:37 PM

Ah ha, that would make sense. Thanks for the reply Tinkerer, much appreciated. smile
© 2020 Larian Studios forums