npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

dice-rng

v1.0.3

Published

![Node.js Version](https://img.shields.io/badge/node.js-%3E%3D%2014.0.0-brightgreen) ![PRNG Strength](https://img.shields.io/badge/randomness-high-yellowgreen) ![Period](https://img.shields.io/badge/period-2%5E128%20--%201-lightgrey) [![License: MIT](http

Readme

📄 dice-rng Module Documentation

Node.js Version PRNG Strength Period License: MIT GitHub Repo

This module provides a fast and reliable pseudo-random number generator (PRNG) using the Xorshift128+ algorithm. Perfect for simulations, games, and applications requiring high-quality randomness without cryptographic requirements.

🚀 Installation

npm install dice-rng

💻 Basic Usage

// ES6 Modules
import diceRng from 'dice-rng';

// CommonJS (if using require)
// const diceRng = require('dice-rng');

// Create generator with random seed
const rng = new diceRng();

// Generate random numbers
console.log(rng.nextRange(1, 6)); // Dice roll: 1-6

🔧 API Reference

new diceRng([seed])

Creates a new generator instance:

  • seed (optional):
    • undefined: Use cryptographically secure random seed (recommended). If result is state [0n, 0n], state1 is automatically set to 1n.
    • BigInt: Single seed. Converted to state using formula:
      state0 = seed
      state1 = seed ^ 0x6a09e667f3bcc909n
      If result is [0n, 0n], state1 is set to 1n.
    • [state0, state1]: Full state as BigInt array (must have exactly 2 elements).
      ⚠️ Cannot be [0n, 0n] - will throw Error.
// Initialization examples
const rng1 = new diceRng(); // Random seed
const rng2 = new diceRng(123456789n); // Fixed seed (note the 'n' for BigInt!)
const rng3 = new diceRng([0x123n, 0xABCn]); // Full state

Generator Methods

.next() → BigInt

Generates a 64-bit random number as BigInt

const bigIntValue = rng.next();
console.log(bigIntValue); // 18643850231453088000n

.nextInt() → Number

Generates a 32-bit integer (0 to 4294967295)

const intValue = rng.nextInt();
console.log(intValue); // 3158275367

.nextDouble() → Number

Generates a double-precision float [0, 1) with 53-bit precision (JavaScript's maximum precision)

const floatValue = rng.nextDouble();
console.log(floatValue); // 0.3578451201923456

.nextRange(min, max) → Number

Generates an integer within range [min, max] (inclusive).
⚠️ Throws error if:

  • min or max is not an integer
  • min >= max
const diceRoll = rng.nextRange(1, 6); // Dice roll: 1-6
const lotteryNumber = rng.nextRange(1, 60); // Lottery number: 1-60

.currentState() → [BigInt, BigInt]

Returns current internal state for debugging

const state = rng.currentState();
console.log(state); // [123456789n, 987654321n]

📖 Usage Examples

Dice Simulation

function rollDice(rng) {
  return rng.nextRange(1, 6);
}

const rng = new diceRng();
console.log('Dice roll result:', rollDice(rng));

Card Deck Shuffling

function shuffleDeck(rng) {
  const suits = ['♠', '♥', '♦', '♣'];
  const values = ['A', '2', '3', '4', '5', '6', '7', '8', '9', '10', 'J', 'Q', 'K'];
  
  const deck = [];
  for (const suit of suits) {
    for (const value of values) {
      deck.push(`${value}${suit}`);
    }
  }
  
  // Fisher-Yates shuffle
  for (let i = deck.length - 1; i > 0; i--) {
    const j = rng.nextRange(0, i); // [0, i] inclusive
    [deck[i], deck[j]] = [deck[j], deck[i]];
  }
  
  return deck;
}

const rng = new diceRng();
const deck = shuffleDeck(rng);
console.log('Top card:', deck[0]);

Procedural World Generation

function generateTerrain(seed) {
  const rng = new diceRng(seed);
  const size = 5;
  let world = "";

  for (let y = 0; y < size; y++) {
    for (let x = 0; x < size; x++) {
      const tile = rng.nextRange(1, 4);
      world +=
        tile === 1
          ? "🌲" // Forest
          : tile === 2
          ? "⛰️" // Mountaint
          : tile === 3
          ? "🌊" // River
          : "🟫"; // Land
    }
    world += "\n";
  }
  return world;
}

const worldSeed = 1234n;
console.log(generateTerrain());
// Output example:
// 🌲⛰️🌊🟫🌲
// 🟫🌲⛰️🌊🟫
// 🌊🟫🌲⛰️🌊
// ⛰️🌊🟫🌲⛰️
// 🌲⛰️🌊🟫🌲



// Use fixed seed for reproducible world
const worldSeed = 2023n; // Note the 'n' for BigInt!
const world = generateWorld(worldSeed, 10, 10);

Dice gambling simulation

class GradualLuckSimulator {
  constructor() {
    this.rng = new Xorshift128Plus();
    this.rollCount = 0;
  }

  roll() {
    this.rollCount++;

    // Luck graph decreases linearly
    const luckFactor = Math.max(0, 1 - (this.rollCount - 1) / 30);

    // Adjust probability based on luck factor
    const rand = this.rng.nextDouble();

    if (rand < 0.2 + 0.6 * luckFactor) {
      // High number (4-6)
      return this.rng.nextRange(4, 6);
    } else {
      // Low number (1-3)
      return this.rng.nextRange(1, 3);
    }
  }
}

// Run simulation with visualization
function runGradualSimulation() {
  const simulator = new GradualLuckSimulator();
  const results = [];

  console.log("===== [ GRADUAL SIMULATION: LUCKY → UNLUCKY ] =====");

  for (let i = 1; i <= 30; i++) {
    const roll = simulator.roll();
    results.push(roll);

    const status = roll >= 4 ? "LUCKY 🎇" : "UNLUCKY 💩";
    const progress =
      "▰".repeat(Math.ceil(i / 2)) + "▱".repeat(15 - Math.ceil(i / 2));

    console.log(
      `[${progress}] Roll ${i
        .toString()
        .padStart(2, " ")}: ${roll} - ${status}`
    );
  }

  // Calculate luck percentage per 10 rolls
  console.log("\n===== [ LUCK TREND ] =====");
  for (let segment = 0; segment < 3; segment++) {
    const segmentResults = results.slice(segment * 10, (segment + 1) * 10);
    const luckyCount = segmentResults.filter(r => r >= 4).length;

    const progressBar = "⬛".repeat(luckyCount) + "⬜".repeat(10 - luckyCount);
    console.log(
      `Rolls ${segment * 10 + 1}-${
        (segment + 1) * 10
      }: ${progressBar} ${luckyCount}/10 (${luckyCount * 10}%)`
    );
  }
}

runGradualSimulation();

❗ Error Handling

This module throws errors in the following cases:

  1. Initialization:
    • Seed array doesn't have exactly 2 elements
    • Resulting state is [0n, 0n]
    • Invalid seed type
  2. nextRange():
    • min or max is not an integer
    • min >= max
  3. Internal Operations:
    • nextDouble() produces value outside [0, 1) (extremely rare)

⚠️ Important Notes

  1. Not for Cryptography
    This module is not suitable for security applications or cryptography

  2. Reproducibility
    Same seed will produce exactly the same sequence of numbers

  3. High Performance
    Capable of generating ~65 million numbers/second on modern CPUs

  4. Compatibility
    Requires Node.js v14.0+ (ES6 modules and BigInt support).
    ⚠️ Must use BigInt for seeds:
    123n (correct) vs 123 (incorrect)

  5. Double Precision
    nextDouble() uses 53-bit precision (not 64-bit) due to JavaScript limitations

  6. Module System
    Code uses ES6 modules (import/export). Ensure package.json has "type": "module" or use .mjs extension

📊 Comparison with Math.random()

Both dice-rng and Math.random() use the same Xorshift128+ algorithm under the hood (in V8 engine), but there are key differences in implementation and features:

| Feature | dice-rng | Math.random() | |--------------------|-----------------------|-----------------------| | Algorithm | Xorshift128+ | Xorshift128+ (V8) | | Seed Control | ✅ Full control | ❌ Auto-seeded | | Reproducibility| ✅ Deterministic | ❌ Non-deterministic | | State Access | ✅ Can inspect/save | ❌ Hidden internal | | Precision | 53-bit | 53-bit | | Period | 2128-1 | 2128-1 | | Performance | Very Fast | Very Fast | | Portability | ✅ Cross-platform | ⚠️ Engine-dependent |

🔧 package.json Configuration

To use ES6 modules, ensure your package.json has:

{
  "name": "dice-rng",
  "type": "module",
  "engines": {
    "node": ">=14.0.0"
  }
}

🎯 Performance Benchmarks

// Quick performance test
const rng = new diceRng();
const start = performance.now();

for (let i = 0; i < 1000000; i++) {
  rng.nextDouble();
}

const elapsed = performance.now() - start;
console.log(`Generated 1M numbers in ${elapsed.toFixed(2)}ms`);

🔬 Algorithm Details

Xorshift128+ is a variant of the Xorshift family of PRNGs:

  • Period: 2^128 - 1
  • State Size: 128 bits (2 × 64-bit values)
  • Operations: XOR, left shift, right shift
  • Quality: Passes most statistical tests
  • Speed: Excellent performance on modern CPUs

Why Use dice-rng Instead of Math.random()?

Since both use the same algorithm, the main advantages of dice-rng are:

  1. 🎯 Reproducibility: Perfect for testing, debugging, and deterministic simulations
  2. 🔧 Control: You can save/restore generator state
  3. 🎮 Gaming: Essential for save/load functionality in games
  4. 🧪 Scientific: Reproducible experiments and research
  5. 🔄 Portability: Same results across different JavaScript engines

📜 License

MIT License. Free to use for personal and commercial projects.


Made with ❤️ for developers who need reliable randomness