veloren_world/util/
random.rs1use super::{Sampler, seed_expan};
2use rand::RngCore;
3use vek::*;
4
5#[derive(Clone, Copy)]
6pub struct RandomField {
7 seed: u32,
8}
9
10impl RandomField {
11 pub const fn new(seed: u32) -> Self { Self { seed } }
12
13 pub fn chance(&self, pos: Vec3<i32>, chance: f32) -> bool { self.get_f32(pos) < chance }
14
15 pub fn get_f32(&self, pos: Vec3<i32>) -> f32 {
16 (self.get(pos) % (1 << 16)) as f32 / ((1 << 16) as f32)
17 }
18
19 pub fn choose<'a, T>(&self, pos: Vec3<i32>, slice: &'a [T]) -> Option<&'a T> {
20 if slice.is_empty() {
21 return None;
22 }
23
24 let i = self.get(pos) as usize;
25 slice.get(i % slice.len())
26 }
27}
28
29impl Sampler<'static> for RandomField {
30 type Index = Vec3<i32>;
31 type Sample = u32;
32
33 fn get(&self, pos: Self::Index) -> Self::Sample {
34 let pos = pos.map(|e| u32::from_le_bytes(e.to_le_bytes()));
35
36 let mut a = self.seed;
37 a = (a ^ 61) ^ (a >> 16);
38 a = a.wrapping_add(a << 3);
39 a ^= pos.x;
40 a ^= a >> 4;
41 a = a.wrapping_mul(0x27d4eb2d);
42 a ^= a >> 15;
43 a ^= pos.y;
44 a = (a ^ 61) ^ (a >> 16);
45 a = a.wrapping_add(a << 3);
46 a ^= a >> 4;
47 a ^= pos.z;
48 a = a.wrapping_mul(0x27d4eb2d);
49 a ^= a >> 15;
50 a
51 }
52}
53
54pub struct RandomPerm {
55 seed: u32,
56}
57
58impl RandomPerm {
59 pub const fn new(seed: u32) -> Self { Self { seed } }
60
61 pub fn chance(&self, perm: u32, chance: f32) -> bool {
62 (self.get(perm) % (1 << 16)) as f32 / ((1 << 16) as f32) < chance
63 }
64}
65
66impl Sampler<'static> for RandomPerm {
67 type Index = u32;
68 type Sample = u32;
69
70 fn get(&self, perm: Self::Index) -> Self::Sample {
71 seed_expan::diffuse_mult(&[self.seed, perm])
72 }
73}
74
75impl RngCore for RandomPerm {
77 fn next_u32(&mut self) -> u32 {
78 self.seed = self.get(self.seed) ^ 0xA7535839;
79 self.seed
80 }
81
82 fn next_u64(&mut self) -> u64 {
83 let a = self.next_u32();
84 let b = self.next_u32();
85 ((a as u64) << 32) | b as u64
86 }
87
88 fn fill_bytes(&mut self, dest: &mut [u8]) {
89 dest.iter_mut()
90 .for_each(|b| *b = (self.next_u32() & 0xFF) as u8);
91 }
92
93 fn try_fill_bytes(&mut self, dest: &mut [u8]) -> Result<(), rand::Error> {
94 self.fill_bytes(dest);
95 Ok(())
96 }
97}