From 7c936ae3f22d529b9db7001ba22277e73b676f04 Mon Sep 17 00:00:00 2001 From: Saagar Date: Sun, 17 May 2026 22:34:44 -0700 Subject: [PATCH] fix: update BattleGrid rand migration - Move workspace rand to 0.9.2 and update renamed API calls. - Enable getrandom 0.3 support for the WebAssembly build. - Add seeded map-generation coverage and dependency notes. Tests: ./scripts/cargo-safe.sh fmt --check Tests: ./scripts/cargo-safe.sh clippy --workspace -- -D warnings Tests: ./scripts/cargo-safe.sh test --workspace Tests: wasm-pack build crates/battleground-wasm --target web Tests: node scripts/ci/require-tests-and-docs.mjs --- .cargo/config.toml | 2 +- Cargo.lock | 45 ++++--------------- Cargo.toml | 2 +- crates/battleground-core/src/map_gen.rs | 4 +- crates/battleground-core/src/simulation.rs | 12 ++--- crates/battleground-core/tests/rand_compat.rs | 39 ++++++++++++++++ crates/battleground-server/src/game.rs | 2 +- crates/battleground-server/src/lobby.rs | 4 +- crates/battleground-wasm/Cargo.toml | 1 + docs/dependency-updates.md | 14 ++++++ 10 files changed, 76 insertions(+), 49 deletions(-) create mode 100644 crates/battleground-core/tests/rand_compat.rs create mode 100644 docs/dependency-updates.md diff --git a/.cargo/config.toml b/.cargo/config.toml index 50372d1..09534a1 100644 --- a/.cargo/config.toml +++ b/.cargo/config.toml @@ -1,2 +1,2 @@ [target.wasm32-unknown-unknown] -rustflags = ["-C", "opt-level=s"] +rustflags = ["-C", "opt-level=s", "--cfg", "getrandom_backend=\"wasm_js\""] diff --git a/Cargo.lock b/Cargo.lock index dfb5003..9bb526c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -89,7 +89,7 @@ name = "battleground-core" version = "0.1.0" dependencies = [ "bincode", - "rand 0.8.5", + "rand", "serde", "thiserror", ] @@ -104,7 +104,7 @@ dependencies = [ "bincode", "dashmap", "futures-util", - "rand 0.8.5", + "rand", "serde", "serde_json", "thiserror", @@ -123,6 +123,7 @@ dependencies = [ "battleground-core", "bincode", "getrandom 0.2.17", + "getrandom 0.3.4", "js-sys", "serde", "serde-wasm-bindgen", @@ -339,9 +340,11 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "899def5c37c4fd7b2664648c28120ecec138e4d395b459e5ca34f9cce2dd77fd" dependencies = [ "cfg-if", + "js-sys", "libc", "r-efi 5.3.0", "wasip2", + "wasm-bindgen", ] [[package]] @@ -691,35 +694,14 @@ version = "6.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f8dcc9c7d52a811697d2151c701e0d08956f92b0e24136cf4cf27b57a6a0d9bf" -[[package]] -name = "rand" -version = "0.8.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" -dependencies = [ - "libc", - "rand_chacha 0.3.1", - "rand_core 0.6.4", -] - [[package]] name = "rand" version = "0.9.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6db2770f06117d490610c7488547d543617b21bfa07796d7a12f6f1bd53850d1" dependencies = [ - "rand_chacha 0.9.0", - "rand_core 0.9.5", -] - -[[package]] -name = "rand_chacha" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" -dependencies = [ - "ppv-lite86", - "rand_core 0.6.4", + "rand_chacha", + "rand_core", ] [[package]] @@ -729,16 +711,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d3022b5f1df60f26e1ffddd6c66e8aa15de382ae63b3a0c1bfc0e4d3e3f325cb" dependencies = [ "ppv-lite86", - "rand_core 0.9.5", -] - -[[package]] -name = "rand_core" -version = "0.6.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" -dependencies = [ - "getrandom 0.2.17", + "rand_core", ] [[package]] @@ -1154,7 +1127,7 @@ dependencies = [ "http", "httparse", "log", - "rand 0.9.2", + "rand", "sha1", "thiserror", ] diff --git a/Cargo.toml b/Cargo.toml index 368e0a8..3d4593a 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -7,4 +7,4 @@ serde = { version = "=1.0.228", features = ["derive"] } bincode = "=1.3.3" thiserror = "=2.0.18" anyhow = "=1.0.102" -rand = "=0.8.5" +rand = "=0.9.2" diff --git a/crates/battleground-core/src/map_gen.rs b/crates/battleground-core/src/map_gen.rs index 932e150..27ed758 100644 --- a/crates/battleground-core/src/map_gen.rs +++ b/crates/battleground-core/src/map_gen.rs @@ -274,7 +274,7 @@ fn generate_noise_field( // Seed each hex with a random base value for hex in hexes { - raw.insert(*hex, rng.gen::()); + raw.insert(*hex, rng.random::()); } // Smooth by averaging with neighbors (2 passes for organic clustering) @@ -355,7 +355,7 @@ fn place_terrain_noise( // Shuffle the pool to add randomness within high-scoring candidates for i in (1..pool.len()).rev() { - let j = rng.gen_range(0..=i); + let j = rng.random_range(0..=i); pool.swap(i, j); } diff --git a/crates/battleground-core/src/simulation.rs b/crates/battleground-core/src/simulation.rs index 52f3398..6f8b0e3 100644 --- a/crates/battleground-core/src/simulation.rs +++ b/crates/battleground-core/src/simulation.rs @@ -1281,24 +1281,24 @@ mod tests { for _ in 0..5.min(left.len()) { let mut hex; loop { - hex = left[rng.gen_range(0..left.len())]; + hex = left[rng.random_range(0..left.len())]; if !used_left.contains(&hex) { break; } } used_left.insert(hex); - state.place_unit(types[rng.gen_range(0..types.len())], PlayerId(0), hex); + state.place_unit(types[rng.random_range(0..types.len())], PlayerId(0), hex); } for _ in 0..5.min(right.len()) { let mut hex; loop { - hex = right[rng.gen_range(0..right.len())]; + hex = right[rng.random_range(0..right.len())]; if !used_right.contains(&hex) { break; } } used_right.insert(hex); - state.place_unit(types[rng.gen_range(0..types.len())], PlayerId(1), hex); + state.place_unit(types[rng.random_range(0..types.len())], PlayerId(1), hex); } } @@ -1311,7 +1311,7 @@ mod tests { for player in &state.players { let mut orders = Vec::new(); for unit in state.units_for_player(player.id) { - let action = match rng.gen_range(0..3) { + let action = match rng.random_range(0..3) { 0 => Action::Hold, 1 => Action::Defend, _ => { @@ -1325,7 +1325,7 @@ mod tests { if passable.is_empty() { Action::Hold } else { - let target = passable[rng.gen_range(0..passable.len())]; + let target = passable[rng.random_range(0..passable.len())]; Action::Move { path: vec![unit.position, target], } diff --git a/crates/battleground-core/tests/rand_compat.rs b/crates/battleground-core/tests/rand_compat.rs new file mode 100644 index 0000000..6b8b9ad --- /dev/null +++ b/crates/battleground-core/tests/rand_compat.rs @@ -0,0 +1,39 @@ +use battleground_core::{ + grid::{HexGrid, Terrain}, + hex::Hex, + map_gen::{generate_map, MapGenConfig}, +}; + +fn terrain_signature(grid: &HexGrid, config: &MapGenConfig) -> Vec<(Hex, Terrain)> { + let mut signature: Vec<_> = Hex::ORIGIN + .hexes_in_range(config.radius as u32) + .into_iter() + .map(|hex| { + let terrain = grid + .get_terrain(&hex) + .expect("generated map should contain every configured hex"); + (hex, terrain) + }) + .collect(); + signature.sort_by_key(|(hex, _)| *hex); + signature +} + +#[test] +fn rand_09_map_generation_remains_seed_deterministic() { + let config = MapGenConfig { + radius: 4, + ..MapGenConfig::default() + }; + + let first = terrain_signature(&generate_map(42, &config), &config); + let second = terrain_signature(&generate_map(42, &config), &config); + let different_seed = terrain_signature(&generate_map(43, &config), &config); + + assert_eq!(first, second); + assert_ne!(first, different_seed); + assert!(first.iter().any(|(_, terrain)| matches!( + terrain, + Terrain::Forest | Terrain::Mountain | Terrain::Water + ))); +} diff --git a/crates/battleground-server/src/game.rs b/crates/battleground-server/src/game.rs index 3af0c88..827dcff 100644 --- a/crates/battleground-server/src/game.rs +++ b/crates/battleground-server/src/game.rs @@ -34,7 +34,7 @@ impl GameInstance { pub fn new(player_names: &[(u8, String)], turn_timer_ms: u64, map_seed: Option) -> Self { let seed = map_seed.unwrap_or_else(|| { use rand::Rng; - rand::thread_rng().gen() + rand::rng().random() }); let map_config = MapGenConfig::default(); diff --git a/crates/battleground-server/src/lobby.rs b/crates/battleground-server/src/lobby.rs index 630ffcf..8cc30ec 100644 --- a/crates/battleground-server/src/lobby.rs +++ b/crates/battleground-server/src/lobby.rs @@ -8,10 +8,10 @@ use crate::state::AppState; /// Generate a 6-character alphanumeric room code. pub fn generate_room_code() -> String { const CHARS: &[u8] = b"ABCDEFGHJKLMNPQRSTUVWXYZ23456789"; // no 0/O/1/I to avoid confusion - let mut rng = rand::thread_rng(); + let mut rng = rand::rng(); (0..6) .map(|_| { - let idx = rng.gen_range(0..CHARS.len()); + let idx = rng.random_range(0..CHARS.len()); CHARS[idx] as char }) .collect() diff --git a/crates/battleground-wasm/Cargo.toml b/crates/battleground-wasm/Cargo.toml index cbdf892..eae3058 100644 --- a/crates/battleground-wasm/Cargo.toml +++ b/crates/battleground-wasm/Cargo.toml @@ -14,3 +14,4 @@ js-sys = "=0.3.77" serde = { workspace = true } bincode = { workspace = true } getrandom = { version = "0.2", features = ["js"] } +getrandom_03 = { package = "getrandom", version = "0.3", features = ["wasm_js"] } diff --git a/docs/dependency-updates.md b/docs/dependency-updates.md new file mode 100644 index 0000000..a7cf790 --- /dev/null +++ b/docs/dependency-updates.md @@ -0,0 +1,14 @@ +# Dependency Updates + +## Rand 0.9 and WebAssembly + +The `rand` 0.9 update pulls in `getrandom` 0.3 for seeded random-number +generation. Because `battleground-wasm` builds for +`wasm32-unknown-unknown`, the WASM target must opt into getrandom's +`wasm_js` backend through Cargo config and a direct feature-bearing +dependency. + +Keep the seeded map-generation coverage in place when touching `rand`, +`getrandom`, or the terrain generation path. It verifies that seeded +generation remains deterministic and that different seeds still produce +different terrain layouts.