Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .cargo/config.toml
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
[target.wasm32-unknown-unknown]
rustflags = ["-C", "opt-level=s"]
rustflags = ["-C", "opt-level=s", "--cfg", "getrandom_backend=\"wasm_js\""]
45 changes: 9 additions & 36 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Enable wasm RNG support for rand 0.9

When building the browser/WASM package, this version bump makes battleground-core pull rand_core 0.9 and getrandom 0.3, but crates/battleground-wasm only enables the old getrandom 0.2 js feature. The Docker build runs wasm-pack build crates/battleground-wasm --target web, and getrandom 0.3 does not support wasm32-unknown-unknown by default without its wasm_js backend/feature, so the WASM/client build regresses even though native Rust checks can still pass.

Useful? React with 👍 / 👎.

4 changes: 2 additions & 2 deletions crates/battleground-core/src/map_gen.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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::<f64>());
raw.insert(*hex, rng.random::<f64>());
}

// Smooth by averaging with neighbors (2 passes for organic clustering)
Expand Down Expand Up @@ -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);
}

Expand Down
12 changes: 6 additions & 6 deletions crates/battleground-core/src/simulation.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}
}

Expand All @@ -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,
_ => {
Expand All @@ -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],
}
Expand Down
39 changes: 39 additions & 0 deletions crates/battleground-core/tests/rand_compat.rs
Original file line number Diff line number Diff line change
@@ -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
)));
}
2 changes: 1 addition & 1 deletion crates/battleground-server/src/game.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ impl GameInstance {
pub fn new(player_names: &[(u8, String)], turn_timer_ms: u64, map_seed: Option<u64>) -> Self {
let seed = map_seed.unwrap_or_else(|| {
use rand::Rng;
rand::thread_rng().gen()
rand::rng().random()
});

let map_config = MapGenConfig::default();
Expand Down
4 changes: 2 additions & 2 deletions crates/battleground-server/src/lobby.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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()
Expand Down
1 change: 1 addition & 0 deletions crates/battleground-wasm/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -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"] }
14 changes: 14 additions & 0 deletions docs/dependency-updates.md
Original file line number Diff line number Diff line change
@@ -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.
Loading