feat(simulation): SeedChain seed-derivation primitive in server/src/seed.rs (#952, D-224)
New top-level seed module that owns every deterministic-RNG primitive: - splitmix64 — the one canonical mixer (was duplicated as a private fn in simulation/rng.rs; EntityRng now imports the shared one, no behavior change) - AtlasRng — moved here from atlas/rng.rs (it is a generation-RNG primitive, not atlas-specific); atlas now depends on seed, not the reverse - SeedDomain — append-only domain tags (Body/Layer1Topography/Layer3Settlement/ Layer4Quarter/Block/Npc) for collision-proof per-domain seed separation - SeedChain — root(world_seed) → derive(domain, id) → atlas_rng()/seed(), per the D-224 formula splitmix64(self ^ splitmix64(domain)) ^ splitmix64(id) Structural move only — SeedChain is not yet threaded through the cascade callers (skeleton_gen still uses ad-hoc wrapping_add pre-mixing); that is the next step. Unit tests cover the splitmix64 known-vector, avalanche, determinism, domain/id separation, and chain composition. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -2,6 +2,7 @@
|
||||
// Injectable ChaCha RNG resource for deterministic replay (D-030)
|
||||
// Ensures same seed produces same outcomes
|
||||
|
||||
use crate::seed::splitmix64;
|
||||
use bevy_ecs::prelude::*;
|
||||
use rand::SeedableRng;
|
||||
use rand_chacha::ChaCha20Rng;
|
||||
@@ -61,16 +62,6 @@ impl EntityRng {
|
||||
}
|
||||
}
|
||||
|
||||
/// Splitmix64 mixing function — good avalanche properties for seed derivation.
|
||||
/// Ensures that similar inputs (e.g., consecutive StableIds) produce
|
||||
/// uncorrelated output seeds.
|
||||
fn splitmix64(mut x: u64) -> u64 {
|
||||
x = x.wrapping_add(0x9e3779b97f4a7c15);
|
||||
x = (x ^ (x >> 30)).wrapping_mul(0xbf58476d1ce4e5b9);
|
||||
x = (x ^ (x >> 27)).wrapping_mul(0x94d049bb133111eb);
|
||||
x ^ (x >> 31)
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
Reference in New Issue
Block a user