Plugin reference

random

A fast, seedable pseudo-random generator (not for cryptography).

8 functionsnamespace randomsource plugins/random/RandomPlugin.c

Portable: Linux (getrandom + pthread) and Windows (BCryptGenRandom + CRITICAL_SECTION); thread-safe with mutex; lazy auto-seed on first call.

Introduction

The random plugin provides a fast, modern pseudo-random number generator callable from scripts. The algorithm is xoshiro256++ (Blackman & Vigna) with a 256-bit internal state and a period of 2^256-1; seeding uses SplitMix64. One global generator lives in the process behind a mutex (Linux: pthread, Windows: CRITICAL_SECTION) -- safe to call from multiple threads.

Range conventions

The integer range (random.Int) is CLOSED: [min, max] with both endpoints inclusive -- for dice rolls (1..6) or array indices (0..N-1). The floating-point output (random.Double, random.Range) is HALF-OPEN: [min, max) -- the upper bound NEVER appears, which is the standard U(0,1) convention (Java, Python, Lua, JavaScript).

Determinism and reproducibility

Given the same seed, output is platform-independent. Two functions support reproducibility: random.Seed(i64) for simple seeding (good for tests and demos), and random.SaveState / random.LoadState which serialize the FULL 256-bit internal state to a 32-byte blob (exact snapshot).

When NOT to use

This is NOT a cryptographically secure generator -- do NOT use it for key material, password-hash salt, or token generation. Use crypto.RandomBytes / crypto.RandomHex instead -- those call the OS CSPRNG (BCryptGenRandom / getrandom) on every call.

Loading the plugin

plugin "builtin:print";
plugin "../plugins/random/RandomPlugin";

A typical flow

// reproducible (for tests)
random.Seed(42);
i64 $d = random.Int(1, 6);
// fresh sequence on every run
random.AutoSeed();
double $u = random.Double();

What to know about every function

  • Every function is thread-safe; one global generator behind a mutex.

  • First call auto-seeds from OS entropy if random.Seed/AutoSeed has not been called.

  • Rejection sampling makes random.Int uniform across the full [min, max] (no modulo bias).

  • random.Double fills [0,1) with full 53-bit mantissa precision.

  • Runtime errors come only from wrong argument count/type or a bad LoadState blob. Reversed bounds (min > max) are swapped with a one-line notice on stderr.

Seeding and state

Seeding the generator from an integer, from OS entropy, or restoring a previous snapshot.

random.Seed

random.Seed(seed) -> int

Sets the global PRNG seed from an i64 value. The implementation uses a SplitMix64 recipe to expand the seed into the 4*u64 internal state words. The same seed always produces the same sequence on any platform.

Parameters
Parameter Type Description
seed i64 The seed value. Any 64-bit integer; 0 is valid.
Return value

Always 0 on success. The only error cases are wrong argument count/type.

Example
random.Seed(42);
printf("%lld\n", random.Int(0, 99));
printf("%lld\n", random.Int(0, 99));
Output after running
51
53
When to use

For tests and reproducible demos. If you want a different sequence on every run, call random.AutoSeed() instead.

random.AutoSeed

random.AutoSeed() -> int

Seeds the generator from OS entropy (Linux: getrandom/urandom; Windows: BCryptGenRandom) and returns the i64 seed that was used. A single call guarantees a different sequence on every run.

Parameters

This function takes no arguments.

Return value

The seed that was used (i64). Following random.Int / random.Double calls will produce a fresh sequence every time the program runs.

Example
i64 $s = random.AutoSeed();
print.Line($"seed used: $s");
printf("first: %lld\n", random.Int(1, 100));
Output after running
seed used: -3829416751029348176
first: 42
When to use

For real applications: games, simulations -- anywhere you want a fresh experience on every start.

random.SaveState

random.SaveState() -> blob

Snapshot of the current 256-bit PRNG state in a 32-byte blob (4 little-endian u64 words). For storage and later restoration.

Parameters

This function takes no arguments.

Return value

32-byte blob; the contents are the full internal state.

Example
random.Seed(100);
random.Int(0, 1000000);
blob $s[32];
$s = random.SaveState();
printf("%d bytes\n", $s.Length);
Output after running
32 bytes
When to use

Reproducible replay: e.g. a demo's 'snapshot' button captures the PRNG in a moment; later restoring it makes the following draws identical.

random.LoadState

random.LoadState(state) -> int

Restores a previously-saved 32-byte state. Rejects the all-zero blob (the xoshiro256++ system would collapse there).

Parameters
Parameter Type Description
state blob Exactly 32 bytes, output of a previous SaveState.
Return value

0 on success. Errors on a wrong-sized blob or all-zero state.

Example
blob $s[32];
random.Seed(100);
random.Int(0, 999999);
$s = random.SaveState();
int $a = random.Int(0, 999999);
random.LoadState($s);
int $b = random.Int(0, 999999);
print.Line($"$a == $b");
Output after running
862054 == 862054
When to use

Deterministic algorithm testing; pausing a long simulation and resuming it later with identical draws.

Number drawing

Integer, double, range, and fair bool -- the typical user-facing surface.

random.Int

random.Int(min, max) -> int

Integer in the CLOSED interval [min, max] (BOTH endpoints inclusive). Uses rejection sampling to avoid modulo bias, so the distribution is uniform across the full range.

Parameters
Parameter Type Description
min i64 Lower bound (inclusive).
max i64 Upper bound (inclusive). If min > max, the bounds are swapped (notice on stderr).
Return value

Integer in [min, max].

Example
random.Seed(42);
printf("dice: %lld\n", random.Int(1, 6));
printf("d100: %lld\n", random.Int(1, 100));
Output after running
dice: 4
d100: 53
When to use

Dice rolls (1..6), array indices (0..N-1), percentages (1..100) -- any classic integer range.

random.Double

random.Double() -> float

Floating-point value in the HALF-OPEN interval [0.0, 1.0) (0.0 is possible, 1.0 is NEVER reached). The full 53-bit mantissa is filled exactly from the top 53 bits of the PRNG output.

Parameters

This function takes no arguments.

Return value

Double in [0.0, 1.0).

Example
random.Seed(1);
printf("u: %f\n", random.Double());
Output after running
u: 0.811612
When to use

For probabilistic decisions (if u < 0.3 -> 30%), interpolation alphas, and any U(0,1)-derived quantity.

random.Range

random.Range(min, max) -> float

Floating-point value in the half-open interval [min, max). min == max simply returns min; min > max swaps the bounds (notice on stderr).

Parameters
Parameter Type Description
min number Lower bound (inclusive).
max number Upper bound (NOT inclusive). If min > max, the bounds are swapped (notice on stderr).
Return value

Double in [min, max).

Example
random.Seed(7);
printf("pos: (%f, %f)\n", random.Range(-1.0, 1.0), random.Range(-1.0,
1.0));
Output after running
pos: (-0.889279, -0.477181)
When to use

For mixed positive/negative float ranges: 2D positions, durations, physical parameters (weight, speed) for random init.

random.Bool

random.Bool() -> int

Fair 0 or 1 value (50/50). Uses the topmost bit of the PRNG output, which is the highest-quality bit of xoshiro256++.

Parameters

This function takes no arguments.

Return value

0 or 1 (DominScript has no native bool, hence i32).

Example
random.Seed(2024);
for i in 1..5 { printf("%d ", random.Bool()); }
print.Line("");
Output after running
1 0 1 1 0
When to use

Coin flips and fair binary decisions. For weighted bool (e.g. 70/30), use random.Double() and compare against 0.7.

Practical notes

Reproducible demos

For demos and test scripts, prefer a fixed random.Seed: this keeps the system tests deterministic, and the output can be diff-checked after each run. For live use (game, application), use random.AutoSeed() instead -- it produces a different internal state on every run.

Weighted choices with Double

For weighted bool (e.g. 70%/30%): `if (random.Double() < 0.7) { ... } else { ... }`. For more buckets, use cumulative thresholds: 60%/30%/10% -> 0.0..0.6, 0.6..0.9, 0.9..1.0.

Error handling

A wrong argument count/type, a LoadState blob with size != 32 bytes, or the all-zero state are reported by the runtime as a runtime error and the script stops. A reversed range (min > max) is not an error: the bounds are swapped and a notice is written to stderr.