BeeneticToolkit.Random 0.12.1

dotnet add package BeeneticToolkit.Random --version 0.12.1
                    
NuGet\Install-Package BeeneticToolkit.Random -Version 0.12.1
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="BeeneticToolkit.Random" Version="0.12.1" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="BeeneticToolkit.Random" Version="0.12.1" />
                    
Directory.Packages.props
<PackageReference Include="BeeneticToolkit.Random" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add BeeneticToolkit.Random --version 0.12.1
                    
#r "nuget: BeeneticToolkit.Random, 0.12.1"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package BeeneticToolkit.Random@0.12.1
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=BeeneticToolkit.Random&version=0.12.1
                    
Install as a Cake Addin
#tool nuget:?package=BeeneticToolkit.Random&version=0.12.1
                    
Install as a Cake Tool

BeeneticToolkit.Random

NuGet Downloads License: MIT

Deterministic, seedable pseudo-random generation for games and simulations.

System.Random gives you one algorithm and no reproducibility guarantees. BeeneticToolkit.Random adds:

  • Seedable, swappable algorithms — xoshiro256** (default), Xorshift, Combined LCG, Middle-Square-Weyl.
  • Reproducible environments — group named generators under a single root seed so an entire run replays from one number.
  • Rich selection helpers — weighted choice, random subsets, exclusions, shuffles, and random enum values.

Not cryptographically secure — designed for game logic, procedural generation, and simulations. Targets netstandard2.1 (modern .NET and Unity).

Install

dotnet add package BeeneticToolkit.Random

Quick start

Generators come from environments — the seedable unit. Create one, register a generator on it, and draw:

using BeeneticToolkit.Random;

var env = new RandomEnvironment("game", rootSeed: 12345);
var rng = env.CreateAndRegister("main");

int roll    = rng.NextInt(1, 7);            // [1, 7)
double unit = rng.NextDouble();             // [0, 1)
bool crit   = rng.NextBool(0.05f);          // 5% chance of true
var dir     = rng.NextEnum<Direction>();    // a random value of your enum
Guid id     = rng.NextGuid();

Just need a number and don't care about reproducibility? Use the shared scratch generator:

int n = RandomManager.Scratch.NextInt(100);   // entropy-seeded, not reproducible

Reproducible environments

Group related generators under one root seed. Each generator's seed is derived from the root and its key, so every stream is independent yet the whole environment replays from a single number:

var world = new RandomEnvironment("world", rootSeed: 2024);
var terrain = world.CreateAndRegister("terrain");
var loot    = world.CreateAndRegister("loot");    // distinct stream, also reproducible

An environment always has a RootSeed. If you don't supply one, a high-entropy seed is generated and recorded — so even an unseeded run can be reproduced after the fact:

var run = new RandomEnvironment("run");           // auto-seeded
long seed = run.RootSeed;                          // capture it to replay this exact run later

Use RandomKey constants instead of raw strings for compile-time safety against typos. Pick a default algorithm per environment, or override per generator:

var env = new RandomEnvironment("sim", rootSeed: 7, algorithm: RandomAlgorithm.CombinedLCG);
var fast = env.CreateAndRegister("fast", algorithm: RandomAlgorithm.Xorshift);

Process-wide access

The global RandomManager is a registry of named environments:

var enemies = RandomManager.CreateEnvironment("enemies", rootSeed: 99);
enemies.CreateAndRegister("spawns");

var sameEnv = RandomManager.GetEnvironment("enemies");
var spawnRng = sameEnv.Get("spawns");

Selection helpers

The selection and shuffle helpers are extension methods on the generator, so the source of randomness is always explicit:

var loot = new[] { "common", "rare", "epic" };
string pick = rng.RandomChoice(loot);

// Weighted — "common" is chosen ~90% of the time.
string weighted = rng.RandomWeightedChoice(
    new[] { ("common", 9.0), ("rare", 1.0) });

// Shuffle returns a new list; ShuffleInPlace mutates in place.
var deck = Enumerable.Range(1, 52).ToList();
List<int> shuffled = rng.Shuffle(deck);
rng.ShuffleInPlace(deck);

// Non-throwing Try* variants are available for all selectors.
if (rng.TryRandomChoice(loot, out string chosen)) { /* ... */ }

Coherent noise

Deterministic, cross-platform value and Perlin noise (2D & 3D) with a fractal/fBm wrapper, in the BeeneticToolkit.Random.Noise namespace. Unlike Unity's Mathf.PerlinNoise, it is seedable and bit-identical across platforms, so procedural content reproduces exactly. Allocation-free scalar sampling.

using BeeneticToolkit.Random.Noise;

INoise perlin = NoiseFactory.Create(NoiseAlgorithm.Perlin, seed: 1337);
float v   = perlin.Sample(x, y);       // [-1, 1]
float v01 = perlin.Sample01(x, y);     // [0, 1]
float cave = perlin.Sample(x, y, z);   // 3D

// Fractal Brownian motion — natural-looking terrain/textures:
var terrain = new FractalNoise(perlin, octaves: 5, frequency: 0.01f);
float height = terrain.Sample(worldX, worldY);

Seed it from an environment's RootSeed to keep noise reproducible alongside the rest of a run:

INoise noise = NoiseFactory.Create(NoiseAlgorithm.Perlin, world.RootSeed);

Poisson-disk point sampling

Blue-noise point distributions (BeeneticToolkit.Random.Sampling) — random points kept at least a minimum distance apart, so they scatter evenly with no clumps or gaps. Ideal for placing vegetation, props, spawns, or decoration; deterministic for a seeded generator.

using BeeneticToolkit.Random.Sampling;

// Points at least 4 units apart, filling a 100x100 region:
IReadOnlyList<(float X, float Y)> points =
    PoissonDisk.Sample(rng, width: 100f, height: 100f, minDistance: 4f);

foreach (var (x, y) in points)
    PlaceTree(x, y);

Spatial point sampling

Single random directions and points inside 2D/3D shapes, as extension methods on the generator (BeeneticToolkit.Random.Sampling). Points inside areas and volumes are uniformly distributed (no center-crowding), and results are returned as value tuples — no allocation, no engine-specific vector type to convert:

using BeeneticToolkit.Random.Sampling;

float angle              = rng.NextAngle();                  // [0, 2π)
(float X, float Y) dir   = rng.NextUnitVector2();            // point on the unit circle
var dir3                 = rng.NextUnitVector3();            // point on the unit sphere

var spawn   = rng.NextPointInCircle(radius: 5f);            // uniform inside a disk
var ring    = rng.NextPointInAnnulus(inner: 3f, outer: 5f); // uniform inside a ring
var inBlast = rng.NextPointInSphere(radius: 2f);            // uniform inside a ball

Probability & loot

Game-ready probability building blocks in the BeeneticToolkit.Random.Probability namespace. Each takes a generator at draw time, so everything is reproducible from a seed:

using BeeneticToolkit.Random.Probability;

// Weighted bag — draw with replacement, or without (the bag depletes).
var bag = new WeightedBag<string>().Add("common", 9).Add("rare", 1);
string drop   = bag.Draw(rng);                    // bag unchanged
string unique = bag.DrawWithoutReplacement(rng);  // removed from the bag

// Loot table — weighted entries, nestable into tiers.
var rares = new LootTable<string>().Add("epic", 3).Add("legendary", 1);
var chest = new LootTable<string>()
    .Add("gold", 80)
    .AddTable(rares, 20);          // 20% chance to roll the rare sub-table
string loot = chest.Roll(rng);
List<string> haul = chest.Roll(rng, count: 5);

// Dice notation — "NdS±M", parse once or roll inline.
int damage = rng.Roll("2d6+1");
var attack = DiceRoll.Parse("1d20+5");
int hit    = attack.Roll(rng);    // attack.Min .. attack.Max

// Gacha pity — base rate, soft-pity ramp, guaranteed at hard pity.
var pity = new PityCounter(baseChance: 0.006, hardPity: 90, softPityStart: 73, softPityIncrement: 0.06);
bool fiveStar = pity.Roll(rng);   // resets the streak on success

Testing & dependency injection

Every helper here — dice, loot, weighted bags, selectors, shuffles, spatial sampling — is keyed to the IRandomGenerator interface, not the concrete generator. So your game logic can depend on the abstraction and take a mock or fixed-sequence fake in tests, while production passes a real seeded generator:

// Logic depends only on the interface…
int AttackRoll(IRandomGenerator rng) => rng.Roll("1d20+5");

// …a real seeded generator in production…
IRandomGenerator rng = new RandomEnvironment("combat", rootSeed: 42).CreateAndRegister("attacks");
int hit = AttackRoll(rng);

// …a mock/fake in a unit test.
int forced = AttackRoll(fakeRng);

Determinism is a property of the seeded instance, not the reference type — passing a generator as IRandomGenerator never changes its stream. (Environment registration still uses the concrete RandomGenerator, since it owns the seeding/reproducibility contract the interface doesn't express.)

Thread safety

Generators are not thread-safe — each draw advances mutable state. For concurrent work, give each thread its own generator from an environment (env.CreateAndRegister(perThreadKey)); because their seeds derive from the shared root, that is both thread-safe and reproducible. RandomManager.Scratch is likewise single-threaded by contract.

License

Licensed under the MIT License.

Product Compatible and additional computed target framework versions.
.NET net5.0 was computed.  net5.0-windows was computed.  net6.0 was computed.  net6.0-android was computed.  net6.0-ios was computed.  net6.0-maccatalyst was computed.  net6.0-macos was computed.  net6.0-tvos was computed.  net6.0-windows was computed.  net7.0 was computed.  net7.0-android was computed.  net7.0-ios was computed.  net7.0-maccatalyst was computed.  net7.0-macos was computed.  net7.0-tvos was computed.  net7.0-windows was computed.  net8.0 is compatible.  net8.0-android was computed.  net8.0-browser was computed.  net8.0-ios was computed.  net8.0-maccatalyst was computed.  net8.0-macos was computed.  net8.0-tvos was computed.  net8.0-windows was computed.  net9.0 was computed.  net9.0-android was computed.  net9.0-browser was computed.  net9.0-ios was computed.  net9.0-maccatalyst was computed.  net9.0-macos was computed.  net9.0-tvos was computed.  net9.0-windows was computed.  net10.0 was computed.  net10.0-android was computed.  net10.0-browser was computed.  net10.0-ios was computed.  net10.0-maccatalyst was computed.  net10.0-macos was computed.  net10.0-tvos was computed.  net10.0-windows was computed. 
.NET Core netcoreapp3.0 was computed.  netcoreapp3.1 was computed. 
.NET Standard netstandard2.1 is compatible. 
MonoAndroid monoandroid was computed. 
MonoMac monomac was computed. 
MonoTouch monotouch was computed. 
Tizen tizen60 was computed. 
Xamarin.iOS xamarinios was computed. 
Xamarin.Mac xamarinmac was computed. 
Xamarin.TVOS xamarintvos was computed. 
Xamarin.WatchOS xamarinwatchos was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.
  • .NETStandard 2.1

    • No dependencies.
  • net8.0

    • No dependencies.

NuGet packages (2)

Showing the top 2 NuGet packages that depend on BeeneticToolkit.Random:

Package Downloads
BeeneticToolkit

Meta-package that references the full BeeneticToolkit family: BeeneticToolkit.Random, BeeneticToolkit.Collections, BeeneticToolkit.Numerics, BeeneticToolkit.Logging, BeeneticToolkit.Spatial, and BeeneticToolkit.BigMath. Install this to get everything, or install the individual packages to take only what you need.

BeeneticToolkit.Godot

Thin Godot shell helpers for the Beenetic game-dev standard: composition-root bootstrap, a Godot logging sink for BeeneticToolkit.Logging, save/offline store, node pooling, and a fixed-step tick driver. Consumes BeeneticToolkit; the pure game core never references this.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
0.12.1 127 7/15/2026
0.12.0 134 7/14/2026
0.11.0 171 7/14/2026
0.10.0 171 6/21/2026