Files
Grovewright/core/tests/mapgen.rs
T
Steven Wroblewski aae0eccc8b Generator für die Testkarte
Baut aus einer Startzahl eine 64 × 64 Felder große Karte mit Rand aus
Grundgestein, Lichtung am Startpunkt, Felsblock daneben, weichem Fels
innen und hartem Fels außen. Die Regeln sind für 300 Startzahlen geprüft.

Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
2026-09-30 20:39:47 +02:00

133 lines
4.0 KiB
Rust

//! Rules the map generator has to keep for every seed.
use grovewright_core::map::{Map, Pos, Terrain};
use grovewright_core::mapgen::{
generate_test_map, outcrop_origin, spawn_pos, HARD_ROCK_DISTANCE, OUTCROP_SIZE,
SPAWN_CLEARING_RADIUS, TEST_MAP_SIZE,
};
/// Number of seeds every rule is checked against.
const SEEDS: u64 = 300;
fn terrain_at(map: &Map, x: i32, y: i32) -> Terrain {
map.get(Pos::new(x, y))
.expect("position is on the map")
.terrain
}
#[test]
fn the_same_seed_gives_the_same_map() {
assert_eq!(generate_test_map(42), generate_test_map(42));
}
#[test]
fn different_seeds_give_different_maps() {
assert_ne!(generate_test_map(1), generate_test_map(2));
}
#[test]
fn the_map_has_the_test_size() {
let map = generate_test_map(0);
assert_eq!((map.width(), map.height()), (TEST_MAP_SIZE, TEST_MAP_SIZE));
}
#[test]
fn bedrock_forms_the_border_and_nothing_else() {
let last = TEST_MAP_SIZE as i32 - 1;
for seed in 0..SEEDS {
let map = generate_test_map(seed);
for y in 0..=last {
for x in 0..=last {
let on_border = x == 0 || y == 0 || x == last || y == last;
let is_bedrock = terrain_at(&map, x, y) == Terrain::Bedrock;
assert_eq!(is_bedrock, on_border, "seed {seed}, tile {x}/{y}");
}
}
}
}
#[test]
fn the_spawn_clearing_is_open_ground() {
for seed in 0..SEEDS {
let map = generate_test_map(seed);
let spawn = spawn_pos(&map);
for dy in -SPAWN_CLEARING_RADIUS..=SPAWN_CLEARING_RADIUS {
for dx in -SPAWN_CLEARING_RADIUS..=SPAWN_CLEARING_RADIUS {
if dx * dx + dy * dy > SPAWN_CLEARING_RADIUS * SPAWN_CLEARING_RADIUS {
continue;
}
let terrain = terrain_at(&map, spawn.x + dx, spawn.y + dy);
assert_eq!(terrain, Terrain::Ground, "seed {seed}, offset {dx}/{dy}");
}
}
}
}
#[test]
fn a_soft_rock_outcrop_lies_next_to_the_clearing() {
for seed in 0..SEEDS {
let map = generate_test_map(seed);
let spawn = spawn_pos(&map);
let origin = outcrop_origin(&map);
assert_eq!(origin.x - spawn.x, SPAWN_CLEARING_RADIUS + 2, "seed {seed}");
for y in origin.y..origin.y + OUTCROP_SIZE {
for x in origin.x..origin.x + OUTCROP_SIZE {
assert_eq!(
terrain_at(&map, x, y),
Terrain::SoftRock,
"seed {seed}, tile {x}/{y}"
);
}
}
}
}
#[test]
fn hard_rock_appears_only_far_from_the_spawn_point() {
let last = TEST_MAP_SIZE as i32 - 1;
for seed in 0..SEEDS {
let map = generate_test_map(seed);
let spawn = spawn_pos(&map);
for y in 1..last {
for x in 1..last {
let far = (x - spawn.x).abs().max((y - spawn.y).abs()) >= HARD_ROCK_DISTANCE;
match terrain_at(&map, x, y) {
Terrain::HardRock => assert!(far, "seed {seed}: hard rock near spawn"),
Terrain::SoftRock => assert!(!far, "seed {seed}: soft rock far out"),
Terrain::Ground | Terrain::Bedrock => {}
}
}
}
}
}
#[test]
fn every_map_mixes_rock_and_open_ground() {
for seed in 0..SEEDS {
let map = generate_test_map(seed);
let total = map.tiles().len();
let rock = map
.tiles()
.iter()
.filter(|tile| !tile.terrain.is_walkable())
.count();
let percent = rock * 100 / total;
assert!(
(20..=80).contains(&percent),
"seed {seed}: {percent} percent rock"
);
let hard = map
.tiles()
.iter()
.filter(|tile| tile.terrain == Terrain::HardRock)
.count();
assert!(hard > 0, "seed {seed}: no hard rock");
}
}
#[test]
fn no_generated_tile_starts_damaged() {
let map = generate_test_map(5);
assert!(map.tiles().iter().all(|tile| tile.damage == 0));
}