Tutorial 07: Standard Library — Random & Noise
Difficulty: Intermediate
Time: ~25 minutes
Prerequisites: Tutorial 06: Math & Particles
What You'll Build
A treasure chest generator that uses random loot tables, value noise for a natural reward multiplier, and binomial sampling for bonus chests — all seeded from a persistent scoreboard value.
What You'll Learn
import random::*— LCG-based pseudo-random numbersnext_lcg,random_range,random_boolbinomial_sample— probabilistic trial countingimport noise::*— smooth procedural noisevalue_noise_1d,fbm_1d,terrain_height
Step 1: The LCG Seed Pattern
RedScript's random module uses a Linear Congruential Generator (LCG). You maintain a seed variable, advance it with next_lcg, and extract values from it:
import random::*
@load
fn setup() {
scoreboard_add_objective("rng_seed", "dummy")
// Initial seed — any non-zero integer
scoreboard_set("#seed", "rng_seed", 987654321)
}
fn advance_seed() -> int {
let seed: int = scoreboard_get("#seed", "rng_seed")
seed = next_lcg(seed)
scoreboard_set("#seed", "rng_seed", seed)
return seed
}Always store the seed in a scoreboard so it persists across ticks and server restarts.
Step 2: random_range
// random_range(seed, lo, hi) → int in [lo, hi) (hi is exclusive)
let seed: int = advance_seed()
let roll: int = random_range(seed, 0, 10) // 0, 1, 2, ... 9Use this for loot tables:
fn pick_loot_item(seed: int) -> string {
let roll: int = random_range(seed, 0, 10)
if (roll < 2) { return "minecraft:diamond" } // 20%
if (roll < 5) { return "minecraft:gold_ingot" } // 30%
if (roll < 8) { return "minecraft:iron_ingot" } // 30%
return "minecraft:bread" // 20%
}Step 3: value_noise_1d — Smooth Randomness
random_range gives independent random values. value_noise_1d gives smooth values that transition gradually — great for natural-feeling rewards:
import noise::*
// value_noise_1d(x_fx) → [0, 10000]
// x_fx is a fixed-point position (×10000)
// Nearby positions return similar values (smooth interpolation)
let seed2: int = advance_seed()
let noise_val: int = value_noise_1d(seed2) // 0..10000
// Map to [1, 3] using linear mapping: 1 + noise * 2 / 10000
let count: int = 1 + noise_val * 2 / 10000 // 1, 2, or 3Step 4: binomial_sample — Probability Trials
binomial_sample(n, p, seed) simulates n independent Bernoulli trials each with probability p and returns the success count:
// binomial_sample(n, p_x10000, seed)
// n=3 trials, p=0.25 (25%) each → returns 0, 1, 2, or 3
let seed3: int = advance_seed()
let bonus: int = binomial_sample(3, 2500, seed3)This is more realistic than random_range for "how many bonus chests" because it naturally clusters around the expected value (0.75 here).
Step 5: The Chest Trigger
@on_trigger("open_chest")
fn open_chest() {
// Step 1: Pick loot type
let seed1: int = advance_seed()
let item: string = pick_loot_item(seed1)
// Step 2: Smooth noise for quantity (1-3)
let seed2: int = advance_seed()
let noise_val: int = value_noise_1d(seed2)
let count: int = 1 + noise_val * 2 / 10000
// Step 3: Bonus chests via binomial
let seed3: int = advance_seed()
let bonus: int = binomial_sample(3, 2500, seed3)
give(@s, item, count)
tell(@s, f"Found: {count}x loot!")
if (bonus > 0) {
tell(@s, f"BONUS: {bonus} extra chests!")
let b: int = 0
while (b < bonus) {
let bseed: int = advance_seed()
give(@s, pick_loot_item(bseed), 1)
b = b + 1
}
}
}Step 6: Terrain Height with FBM
For natural-looking terrain generation, use fbm_1d or the convenience function terrain_height:
// terrain_height(x, z, base_y, amplitude)
// Uses 3-octave FBM noise under the hood
let h: int = terrain_height(10, 5, 64, 20) // base=64, ±20 blocks variationFBM (Fractal Brownian Motion) stacks multiple noise octaves for rich, natural variation:
// fbm_1d(x_fx, octaves, persistence_fx)
// persistence=5000 means each octave is half the amplitude of the previous
let n: int = fbm_1d(50000, 4, 5000) // x=5.0, 4 octaves, persistence=0.5Complete Code
Full example: tutorial_07_random.mcrs
Try It Out
- Install and
/reload /trigger open_chestseveral times — observe varied loot and quantities/trigger terrain_demo— see noise-based heights for coordinates/trigger fbm_demo— see FBM values for 8 positions/trigger coin_flip— 50/50 random bool
Random vs Noise
| Use case | Function | Notes |
|---|---|---|
| Independent random events | random_range, random_bool | Each call is independent |
| Smooth value over space | value_noise_1d/2d | Nearby points → similar values |
| Rich terrain variation | fbm_1d/2d | Multi-octave smooth noise |
| Count successes in n trials | binomial_sample | More realistic than simple % |
| Terrain generation | terrain_height | Convenience wrapper for fbm_2d |