Random
Seeded Random PRNG, coordinate hashes, and Value/Perlin/Simplex pattern noise for procedural worlds.
Seeded, deterministic pseudo-random numbers for demos and games. The Random class uses a mulberry32 core so the same
seed always produces the same sequence across platforms. Stateless hash1i / hash2i / hash3i (and float forms) give
per-coordinate randomness for chunked worlds without storing an RNG per cell. ValueNoise, PerlinNoise, and
SimplexNoise add smooth pattern-based fields for terrain, clouds, and organic motion.
Random Since 1.5.0
import { } from 'blit386';
const = new (1234);
.(); // [0, 1)
.(0, 10); // [0, 10)
.(6); // [0, 6)
.(10, 20); // [10, 20)
.(1, 6); // [1, 6]
.(0.25); // true ~25% of the time
.(); // -1 or 1
.(['a', 'b', 'c']);
.([1, 2, 3, 4]);
.(); // [0, 2π) radians
.(0, 1); // Box-Muller sample
.(); // cardinal unit vectorOmit the constructor seed to time-seed from Date.now() (lower 32 bits). Call seed(n) later to restart from a known
value.
Engine default (BT.random)
BT.random Since 1.5.0
BT.randomSeed Since 1.5.0
The engine keeps one shared Random instance on the BT facade. BT.random is a live reference (same instance across
reads, like BT.palette). It is time-seeded when the engine singleton is created; call BT.randomSeed(seed) to make a
run reproducible.
import { } from 'blit386';
.(42);
..(150, 420);
..(['glitch', 'noise', 'static']);
..(0.3, 0.95);Prefer BT.random for demo and game code. Construct a separate new Random(seed) when you need an independent stream
(for example a local procedural subsystem that should not advance the shared engine RNG).
Generators
| Method | Range / behavior |
|---|---|
next() | Float in [0, 1) |
float(min, max) | Float in [min, max) |
int(maxExclusive) | Integer in [0, maxExclusive) |
int(min, maxExclusive) | Integer in [min, maxExclusive) |
intInclusive(min, max) | Integer in [min, max] |
bool(probability?) | true with the given chance (default 0.5) |
sign() | -1 or 1 |
pick(arr) | One element from a non-empty array |
shuffle(arr) | New shuffled copy (Fisher-Yates) |
shuffleInPlace(arr) | Shuffle the array in place and return it |
weighted(items, weights) | One item by relative non-negative weights |
angle() | Float in [0, 2π) radians |
gaussian(mean?, stddev?) | Approximate normal sample (Box-Muller, no spare) |
insideRect(rect) | Integer point in half-open rect |
insideRectTo(rect, out) | Same as insideRect, writes into out |
pointInRange(min, max) | Integer point; per-axis [min, max) |
pointInRangeTo(min, max, out) | Same as pointInRange, writes into out |
direction4() | One of four cardinal unit vectors (Y-down) |
direction8() | One of eight king-move unit vectors (Y-down) |
Integer helpers return true integers (| 0 truncation), matching the engine's Vector2i philosophy. Half-open int
ranges match the demo helpers (randInt / randFloat).
Spatial helpers
insideRect / insideRectTo sample the same half-open region as Rect2i.isContaining: x in [rect.x, rect.right),
y in [rect.y, rect.bottom). pointInRange / pointInRangeTo use int per axis ([min.x, max.x) and
[min.y, max.y)). Empty or inverted ranges throw the same RangeError as int. Prefer the *To(out) variants in
update() / render() loops to avoid per-frame allocation.
import { , , } from 'blit386';
const = new (7);
const = new (0, 0, 320, 240);
const = new ();
.();
.(, );
.(new (10, 10), new (20, 30));
.(); // (1,0) | (-1,0) | (0,1) | (0,-1)
.(); // cardinals plus diagonalsCoordinate hashing
Stateless spatial lookups for chunked and procedural worlds. Same coordinates and seed always return the same value - no
stored RNG state, so you do not need an instance per chunk. Complements Random (a sequence generator).
hash1i Since 1.5.0
hash2i Since 1.5.0
hash3i Since 1.5.0
hash1 Since 1.5.0
hash2 Since 1.5.0
hash3 Since 1.5.0
| Function | Range |
|---|---|
hash1i(x, seed?) | Unsigned 32-bit in [0, 2^32) |
hash2i(x, y, seed?) | Unsigned 32-bit in [0, 2^32) |
hash3i(x, y, z, seed?) | Unsigned 32-bit in [0, 2^32) |
hash1(x, seed?) | Float in [0, 1) |
hash2(x, y, seed?) | Float in [0, 1) |
hash3(x, y, z, seed?) | Float in [0, 1) |
Coordinates are truncated toward zero with | 0. Omit seed (or pass 0) for a fixed default world seed. Float forms
are the matching hashNi value scaled by 1 / 2^32.
import { , } from 'blit386';
const = (12, -3, 9001); // uint32, same every call
const = (12, -3, 9001); // [0, 1)
const = < 0.15;Pattern noise
Smooth, seedable spatial noise for terrain, clouds, organic motion, and procedural textures. Lattice corners use the
coordinate hashes above. Every sample is in approximately [-1, 1] (the same signed range as trig helpers). These
classes are distinct from the post-process Noise display effect (GPU grain).
ValueNoise Since 1.5.0
PerlinNoise Since 1.5.0
SimplexNoise Since 1.5.0
| Class | Methods |
|---|---|
ValueNoise | noise1D / noise2D / noise3D, fbm1D / fbm2D / fbm3D |
PerlinNoise | Same surface as ValueNoise (gradient Perlin) |
SimplexNoise | noise2D / noise3D, fbm2D / fbm3D (no 1D) |
Omit the constructor seed (or pass 0) for a fixed default world seed - same convention as hash2i. Call seed(n) to
switch fields. fBm defaults: octaves = 4, persistence = 0.5, lacunarity = 2. Octave amplitudes are normalized so
fBm stays in approximately [-1, 1].
import { , , } from 'blit386';
const = new (9001);
const = new (9001);
const = new (9001);
.(12.5, -3.25); // [-1, 1]
.(0.1, 0.2); // multi-octave, still ~[-1, 1]
.(1, 2, 3);Value noise interpolates hashed corner values (smooth but can look blocky at low frequency). Perlin uses lattice gradients (Ken Perlin, SIGGRAPH 2002). Simplex reduces directional artifacts on square grids (Stefan Gustavson).
State and streams
import { } from 'blit386';
const = new (99);
.();
.();
const = .();
const = .(); // same stream from this point
const = .(); // independent sub-stream; advances `rng` once
.(); // restore and replay| Method | Behavior |
|---|---|
seed(n) | Reseed; same n restarts the same sequence |
getState() | Current unsigned 32-bit state |
setState(n) | Restore a saved state |
clone() | New instance with identical state (identical subsequent draws) |
fork() | Advance this instance once; seed a child so the two streams diverge |
seedValue | Last seed passed to the constructor or seed(); undefined after setState(), or on a forked child |
seedValue reads back the seed itself, not the current position in the sequence - the value getState() returns keeps
changing as you draw, but seedValue stays put until the generator is genuinely reseeded. It is normalized to an
unsigned 32-bit value, the same representation getState() uses, not necessarily the raw number passed in. setState()
clears it, since jumping to an arbitrary saved state does not correspond to any known seed. clone() copies it verbatim
(including undefined), matching the identical stream a clone produces. fork()'s child always reports undefined - a
fork is a new stream and should not claim a seed its caller never chose.
API history
| Symbol | Since | Last changed | Status |
|---|---|---|---|
BT.random | 1.5.0 | – | stable |
BT.randomSeed | 1.5.0 | – | stable |
hash1 | 1.5.0 | – | stable |
hash1i | 1.5.0 | – | stable |
hash2 | 1.5.0 | – | stable |
hash2i | 1.5.0 | – | stable |
hash3 | 1.5.0 | – | stable |
hash3i | 1.5.0 | – | stable |
PerlinNoise | 1.5.0 | – | stable |
Random | 1.5.0 | – | stable |
SimplexNoise | 1.5.0 | – | stable |
ValueNoise | 1.5.0 | – | stable |
1.5.0 - Tue Aug 11 2026
- Added
BT.random - Added
BT.randomSeed - Added
PerlinNoise - Added
Random - Added
SimplexNoise - Added
ValueNoise - Added
hash1 - Added
hash1i - Added
hash2 - Added
hash2i - Added
hash3 - Added
hash3i
See also
API: Core Types
API: Audio
Last updated on September 9, 2026