diff --git a/crates/sb-api/src/routes/mod.rs b/crates/sb-api/src/routes/mod.rs index 343fc10..edd8d65 100644 --- a/crates/sb-api/src/routes/mod.rs +++ b/crates/sb-api/src/routes/mod.rs @@ -25,11 +25,6 @@ use sb_shared::{ use std::sync::Arc; use tokio::sync::RwLock; -fn request_rng() -> rand::rngs::StdRng { - use rand::SeedableRng; - rand::rngs::StdRng::from_os_rng() -} - pub(crate) struct AppState { users: RwLock>, items: Vec, @@ -290,10 +285,7 @@ async fn create_character( return Err(axum::http::StatusCode::BAD_REQUEST); } - let mut char = { - let mut rng = request_rng(); - character::create_character(&mut rng, user_id, name, input.race, input.class) - }; + let mut char = character::create_character(user_id, name, input.race, input.class); { let mut id = state.next_char_id.write().await; @@ -432,8 +424,6 @@ async fn run_adventure( .unwrap() .as_millis() as i64; - let mut rng = request_rng(); - let (char, enemy_def) = { let mut chars = state.characters.write().await; let char = chars.iter_mut().find(|c| c.id == char_id) @@ -449,6 +439,7 @@ async fn run_adventure( } char.nerve -= zone.nerve_cost; + let mut rng = rand::rng(); let enemy = domain::pick_enemy(&mut rng, &zone.encounters, &state.enemies); (char.clone(), enemy) }; @@ -503,13 +494,14 @@ async fn run_adventure( songs::BARD_SONGS.iter().find(|s| s.id == sid).map(|s| s.combat_effect) }), spell_effect.as_ref(), - &mut rng, + &mut rand::rng(), ); let (loot_names, updated_char) = { let mut chars = state.characters.write().await; let dropped_ids: Vec = if let Some(c) = chars.iter_mut().find(|c| c.id == char_id) { use rand::Rng; + let mut rng = rand::rng(); if log.winner == c.name { c.xp += log.xp_gained as i64; diff --git a/crates/sb-core/src/character.rs b/crates/sb-core/src/character.rs index 927fe04..1c89d2d 100644 --- a/crates/sb-core/src/character.rs +++ b/crates/sb-core/src/character.rs @@ -126,15 +126,10 @@ pub fn training_cost(stat: i64) -> i32 { (5.0_f64 * 1.3_f64.powi(scaled)) as i32 } -pub fn create_character( - rng: &mut impl rand::Rng, - user_id: u32, - name: String, - race: Race, - class: Class, -) -> Character { +pub fn create_character(user_id: u32, name: String, race: Race, class: Class) -> Character { + let mut rng = rand::rng(); let class_str = class.as_str().to_string(); - let stats = roll_stats(rng, &race); + let stats = roll_stats(&mut rng, &race); let max_hp = calc_max_hp(&class, &stats); let max_energy = calc_max_energy(&class); let max_nerve = calc_max_nerve(&class); @@ -417,28 +412,4 @@ mod tests { assert!(dwarf.strength > human.strength); assert!(dwarf.intelligence < human.intelligence); } - - #[test] - fn create_character_is_deterministic_under_seeded_rng() { - use rand::SeedableRng; - let first = create_character( - &mut rand::rngs::StdRng::seed_from_u64(42), - 7, - "Twin".into(), - Race::Human, - Class::Warrior, - ); - let second = create_character( - &mut rand::rngs::StdRng::seed_from_u64(42), - 7, - "Twin".into(), - Race::Human, - Class::Warrior, - ); - assert_eq!(format!("{:?}", first.stats), format!("{:?}", second.stats)); - assert_eq!(first.hp, second.hp); - assert_eq!(first.max_hp, second.max_hp); - assert_eq!(first.energy, second.energy); - assert_eq!(first.nerve, second.nerve); - } }