# Deterministic Pseudo-Random Number Generation Strategy in Arnis

> Discover Arnis deterministic pseudo-random number generation strategy using ChaCha8 RNG and OSM element IDs for reproducible Minecraft worlds. Ensure identical generation every time.

- Repository: [Louis Erbkamm/arnis](https://github.com/louis-e/arnis)
- Tags: internals
- Published: 2026-03-20

---

**Arnis seeds ChaCha8 RNG instances directly from immutable OSM element IDs and block coordinates, guaranteeing that identical OpenStreetMap data always produces identical Minecraft worlds regardless of generation order or region boundaries.**

Deterministic pseudo-random number generation forms the mathematical foundation of Arnis's reproducible world generation system. By deriving random seeds from immutable OpenStreetMap identifiers and spatial coordinates rather than system time or global state, the codebase ensures that vegetation patterns, building variations, and decorative elements remain visually consistent across incremental world updates and distributed generation tasks. This strategy is implemented through a specialized RNG module that provides three tightly-coupled seeding mechanisms tailored to different procedural generation contexts.

## Element-Based Seeding for Consistent Randomness

The primary mechanism for deterministic randomness in Arnis leverages **element-based seeding**, where each OSM element (node, way, or relation) contributes its unique 64-bit identifier to initialize the random number generator.

In [`src/deterministic_rng.rs`](https://github.com/louis-e/arnis/blob/main/src/deterministic_rng.rs), the `element_rng` function creates a ChaCha8 RNG seeded directly from the element ID:

```rust
// From src/deterministic_rng.rs, lines 29-31
pub fn element_rng(element_id: u64) -> ChaCha8Rng {
    ChaCha8Rng::seed_from_u64(element_id)
}

```

This function appears throughout the element processing modules. For example, in [`src/element_processing/natural.rs`](https://github.com/louis-e/arnis/blob/main/src/element_processing/natural.rs), the RNG determines tree selection and vegetation density (lines 78-82), while [`src/element_processing/leisure.rs`](https://github.com/louis-e/arnis/blob/main/src/element_processing/leisure.rs) uses it for park decoration placement (lines 89-91). Because the seed derives from the immutable OSM ID, processing the same element in different regions or at different times always yields identical random choices.

## Salted Variants for Multiple Independent Streams

A single OSM element often requires multiple independent random sequences—such as separate decisions for wall color and roof style. To prevent correlation between these streams while maintaining determinism, Arnis implements **salted seeding** through the `element_rng_salted` function.

Located in [`src/deterministic_rng.rs`](https://github.com/louis-e/arnis/blob/main/src/deterministic_rng.rs) (lines 45-48), this function XORs a user-provided salt with the element ID before seeding the RNG:

```rust
// From src/deterministic_rng.rs, lines 45-48
pub fn element_rng_salted(element_id: u64, salt: u64) -> ChaCha8Rng {
    let seed = element_id ^ salt;
    ChaCha8Rng::seed_from_u64(seed)
}

```

This approach guarantees that `element_rng_salted(id, 0xA5A5)` and `element_rng_salted(id, 0x5A5A)` produce entirely different, non-colliding sequences for the same element, while remaining deterministic across generation runs.

## Coordinate-Based Seeding for Per-Block Randomness

When randomness must correlate with specific spatial locations rather than OSM elements, Arnis uses **coordinate-based seeding**. The `coord_rng` function generates deterministic randomness from block coordinates, ensuring that the same physical location always receives the same random values even when generated across different region boundaries.

Implemented in [`src/deterministic_rng.rs`](https://github.com/louis-e/arnis/blob/main/src/deterministic_rng.rs) (lines 60-66), this function hashes the X and Z coordinates together with the element ID:

```rust
// From src/deterministic_rng.rs, lines 60-66
pub fn coord_rng(x: i32, z: i32, element_id: u64) -> ChaCha8Rng {
    let x = x as u64;
    let z = z as u64;
    let seed = element_id.wrapping_add(x.wrapping_mul(31).wrapping_add(z));
    ChaCha8Rng::seed_from_u64(seed)
}

```

This technique is essential for features like flower placement within natural areas, where each block position requires its own deterministic random choice that remains consistent regardless of generation order.

## Implementation in Element Processors

The deterministic RNG utilities integrate directly into Arnis's element processing pipeline. Both [`src/element_processing/natural.rs`](https://github.com/louis-e/arnis/blob/main/src/element_processing/natural.rs) and [`src/element_processing/leisure.rs`](https://github.com/louis-e/arnis/blob/main/src/element_processing/leisure.rs) import and invoke `element_rng` to make aesthetic decisions that must remain stable across world regenerations.

By seeding from OSM element IDs at lines 78-82 in [`natural.rs`](https://github.com/louis-e/arnis/blob/main/natural.rs) and lines 89-91 in [`leisure.rs`](https://github.com/louis-e/arnis/blob/main/leisure.rs), the codebase ensures that vegetation distribution, building variations, and decorative elements appear identical every time the same map region is processed. This deterministic approach eliminates visual seams when worlds are generated incrementally or across distributed systems.

## Summary

Arnis achieves reproducible world generation through a deterministic pseudo-random number generation strategy built on three core mechanisms:

- **Element-based seeding**: Uses OSM element IDs to seed ChaCha8 RNG instances via `element_rng`, ensuring identical random sequences for the same geographic features regardless of processing order.
- **Salted variants**: Provides independent random streams through `element_rng_salted`, allowing multiple uncorrelated decisions per element while maintaining determinism.
- **Coordinate-based seeding**: Generates per-block randomness via `coord_rng` by hashing spatial coordinates with element IDs, guaranteeing consistent block-level details across region boundaries.

These utilities, centralized in [`src/deterministic_rng.rs`](https://github.com/louis-e/arnis/blob/main/src/deterministic_rng.rs) and applied throughout the element processing modules, ensure that Arnis worlds are visually identical every time they are generated from the same OpenStreetMap data.

## Frequently Asked Questions

### How does Arnis ensure the same OSM element generates the same Minecraft blocks every time?

Arnis extracts the unique 64-bit identifier from each OpenStreetMap element and uses it to seed a ChaCha8 RNG through the `element_rng` function. Because OSM IDs are immutable and the RNG algorithm is deterministic, the same element always produces the same sequence of random decisions, resulting in identical block placement across regeneration.

### What is the purpose of salt in the deterministic RNG functions?

The salt parameter in `element_rng_salted` allows the generator to produce multiple independent random streams from a single OSM element. By XORing a user-provided salt value with the element ID before seeding, the function creates distinct RNG instances that do not correlate with each other, enabling separate random choices for different attributes while maintaining overall determinism.

### Why does Arnis use ChaCha8 specifically for world generation?

ChaCha8 provides a high-quality, fast, and deterministic pseudo-random number generation algorithm well-suited for procedural content generation. Its statistical properties ensure that seeded sequences appear random without noticeable patterns, while its deterministic nature guarantees that the same seed always produces the same sequence—essential for reproducible world generation in Arnis.

### How does coordinate-based seeding handle region boundaries?

The `coord_rng` function combines absolute block coordinates (X and Z) with the element ID to create a unique seed for each spatial position. Because the seeding algorithm incorporates absolute world coordinates rather than relative chunk offsets, the same physical block will always generate the same random values regardless of which region file is processed first or whether the world is generated incrementally. This eliminates visual seams at region boundaries.