Difference between revisions of "SIBR:Random number generator"
m |
(Add RNG details) |
||
Line 2: | Line 2: | ||
XorShift128+ is not [[Wikipedia:Cryptographically-secure pseudorandom number generator|cryptographically secure]]. With three known consecutive outputs, the RNG state can be fully reconstructed,<ref>https://blog.securityevaluators.com/hacking-the-javascript-lottery-80cc437e3b7f</ref> allowing us to determine what all subsequent values would be. Furthermore, the algorithm is fully reversible so we can determine all preceding values as well.<ref>https://blog.securityevaluators.com/xorshift128-backward-ff3365dc0c17</ref> Using this technique, we can select a player whose earliest recorded stats were unchanged since generation, recover the RNG state from when that player was created, and examine the surrounding values to find stats for other players that were created at the same time. | XorShift128+ is not [[Wikipedia:Cryptographically-secure pseudorandom number generator|cryptographically secure]]. With three known consecutive outputs, the RNG state can be fully reconstructed,<ref>https://blog.securityevaluators.com/hacking-the-javascript-lottery-80cc437e3b7f</ref> allowing us to determine what all subsequent values would be. Furthermore, the algorithm is fully reversible so we can determine all preceding values as well.<ref>https://blog.securityevaluators.com/xorshift128-backward-ff3365dc0c17</ref> Using this technique, we can select a player whose earliest recorded stats were unchanged since generation, recover the RNG state from when that player was created, and examine the surrounding values to find stats for other players that were created at the same time. | ||
+ | |||
+ | ==RNG details== | ||
+ | XorShift128+ uses two 64-bit state variables, which we call <code>s0</code> and <code>s1</code>. Knowing the value of these for a given output value is sufficient to recreate the RNG output both forward and backward from that point. However, the Blaseball sim uses Node.js running on the V8 Javascript engine, which introduces a complication: XorShift128+ is used to pre-generate a batch of 64 random values, which are then returned in reverse order. When correlating known values with the expected RNG output, we must determine where the boundaries are for these blocks and reverse each set of 64 values. | ||
+ | |||
+ | Therefore, we use a triple of <code>(s0, s1, offset)</code> to fully describe a point in the output stream, where <code>offset</code> is the index within a 64-value block. For example, <code>(78357228809041901, 13627021481113128807, 29)</code> gives us the [https://rng.sibr.dev/?s0=78357228809041901&s1=13627021481113128807&offset=29 first of the series of rolls] used to generate [[Lars Taylor]] prior to Season 1. | ||
==Player generation== | ==Player generation== |
Revision as of 12:52, 19 August 2021
The Blaseball backend uses a pseudorandom number generator called XorShift128+ to generate random values. These values are used for a variety of purposes, including attributes for newly-hatched players and determining event outcomes during games.
XorShift128+ is not cryptographically secure. With three known consecutive outputs, the RNG state can be fully reconstructed,[1] allowing us to determine what all subsequent values would be. Furthermore, the algorithm is fully reversible so we can determine all preceding values as well.[2] Using this technique, we can select a player whose earliest recorded stats were unchanged since generation, recover the RNG state from when that player was created, and examine the surrounding values to find stats for other players that were created at the same time.
RNG details
XorShift128+ uses two 64-bit state variables, which we call s0
and s1
. Knowing the value of these for a given output value is sufficient to recreate the RNG output both forward and backward from that point. However, the Blaseball sim uses Node.js running on the V8 Javascript engine, which introduces a complication: XorShift128+ is used to pre-generate a batch of 64 random values, which are then returned in reverse order. When correlating known values with the expected RNG output, we must determine where the boundaries are for these blocks and reverse each set of 64 values.
Therefore, we use a triple of (s0, s1, offset)
to fully describe a point in the output stream, where offset
is the index within a 64-value block. For example, (78357228809041901, 13627021481113128807, 29)
gives us the first of the series of rolls used to generate Lars Taylor prior to Season 1.
Player generation
When a new player is created, their attributes are generated by a series of consecutive rolls in the following order:
first name last name thwackability moxie divinity musclitude patheticism buoyancy baseThirst laserlikeness groundFriction continuation indulgence martyrdom tragicness shakespearianism suppression unthwackability coldness overpowerment ruthlessness omniscience tenaciousness watchfulness anticapitalism chasiness pressurization cinnamon, if player has 'cinnamon' field soul = floor(rand()*8+2) allergy = rand() < 0.5, if player has 'peanutAllergy' field fate = floor(rand()*100), if player has 'fate' field ritual (value unknown), if s12 or later blood = floor(rand()*13), if s12 or later coffee = floor(rand()*13), if s12 or later