rustraight 0.5.2

A simple 2D game library for Rust, inspired by DXLib
// rng.rs — 外部クレートに依存しない軽量な擬似乱数生成器(xorshift64*)を提供する。

use std::cell::RefCell;
use std::time::{SystemTime, UNIX_EPOCH};

struct RngState {
    state: u64,
}

impl RngState {
    fn from_seed(seed: u64) -> Self {
        // xorshift は状態 0 から抜け出せないため奇数化しておく。
        Self { state: seed | 1 }
    }

    fn new() -> Self {
        let seed = SystemTime::now()
            .duration_since(UNIX_EPOCH)
            .map(|d| d.as_nanos() as u64)
            .unwrap_or(0x9E3779B97F4A7C15);
        Self::from_seed(seed)
    }

    fn next_u64(&mut self) -> u64 {
        let mut x = self.state;
        x ^= x >> 12;
        x ^= x << 25;
        x ^= x >> 27;
        self.state = x;
        x.wrapping_mul(0x2545_F491_4F6C_DD1D)
    }
}

thread_local! {
    static RNG: RefCell<RngState> = RefCell::new(RngState::new());
}

/// `min..=max` の範囲で一様乱数を返す(`min > max` の場合は入れ替えて扱う)。
pub fn rand_range(min: i32, max: i32) -> i32 {
    let (lo, hi) = if min <= max { (min, max) } else { (max, min) };
    let span = (hi - lo) as u64 + 1;
    RNG.with(|r| {
        let v = r.borrow_mut().next_u64();
        lo + (v % span) as i32
    })
}

/// `0.0..1.0` の範囲で一様乱数を返す。
pub fn rand_f32() -> f32 {
    RNG.with(|r| {
        let v = r.borrow_mut().next_u64();
        (v >> 40) as f32 / (1u32 << 24) as f32
    })
}

/// 現在スレッドの乱数生成器を指定シードで明示的に再設定する(テスト・リプレイの再現用)。
pub fn seed_rng(seed: u64) {
    RNG.with(|r| *r.borrow_mut() = RngState::from_seed(seed));
}