WI-1: injectable RNG - request_rng() single construction point (StdRng::from_os_rng), thread rng through create_character and run_adventure, seeded determinism test (PSP1, issue #1)

This commit is contained in:
Jan-Peter von Hunnius 2026-10-03 09:56:41 +02:00
parent 64e081aeb7
commit 61fef27917
2 changed files with 44 additions and 7 deletions

View file

@ -25,6 +25,11 @@ 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<Vec<User>>,
items: Vec<Item>,
@ -285,7 +290,10 @@ async fn create_character(
return Err(axum::http::StatusCode::BAD_REQUEST);
}
let mut char = character::create_character(user_id, name, input.race, input.class);
let mut char = {
let mut rng = request_rng();
character::create_character(&mut rng, user_id, name, input.race, input.class)
};
{
let mut id = state.next_char_id.write().await;
@ -424,6 +432,8 @@ 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)
@ -439,7 +449,6 @@ 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)
};
@ -494,14 +503,13 @@ async fn run_adventure(
songs::BARD_SONGS.iter().find(|s| s.id == sid).map(|s| s.combat_effect)
}),
spell_effect.as_ref(),
&mut rand::rng(),
&mut rng,
);
let (loot_names, updated_char) = {
let mut chars = state.characters.write().await;
let dropped_ids: Vec<String> = 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;