aether-shards/test/utils/SeededRandom.test.js
2025-12-17 11:26:42 -08:00

67 lines
1.9 KiB
JavaScript

import { expect } from "@esm-bundle/chai";
import { VoxelGrid } from "../../src/grid/VoxelGrid.js";
import { RuinGenerator } from "../../src/generation/RuinGenerator.js";
describe("System: Procedural Generation (Scatter)", () => {
let grid;
beforeEach(() => {
grid = new VoxelGrid(20, 5, 20);
});
it("CoA 1: scatterCover should place objects on valid floors", () => {
const gen = new RuinGenerator(grid, 12345);
// 1. Generate empty rooms first
gen.generate(1, 10, 10);
// 2. Count empty floor tiles (Air above Stone)
let floorCount = 0;
for (let x = 0; x < 20; x++) {
for (let z = 0; z < 20; z++) {
if (grid.getCell(x, 1, z) === 0 && grid.getCell(x, 0, z) === 1) {
floorCount++;
}
}
}
// 3. Scatter Cover (ID 10) at 50% density
gen.scatterCover(10, 0.5);
// 4. Count Cover
let coverCount = 0;
for (let x = 0; x < 20; x++) {
for (let z = 0; z < 20; z++) {
if (grid.getCell(x, 1, z) === 10) {
coverCount++;
}
}
}
// Expect roughly 50% of the floor to be covered
// We use a range because RNG varies slightly
const expectedMin = floorCount * 0.4;
const expectedMax = floorCount * 0.6;
expect(coverCount).to.be.within(expectedMin, expectedMax);
});
it("CoA 2: scatterCover should NOT place objects in mid-air", () => {
const gen = new RuinGenerator(grid, 12345);
gen.generate();
gen.scatterCover(10, 1.0); // 100% density to force errors if logic is wrong
// Scan for floating cover
for (let x = 0; x < 20; x++) {
for (let z = 0; z < 20; z++) {
for (let y = 1; y < 4; y++) {
if (grid.getCell(x, y, z) === 10) {
const below = grid.getCell(x, y - 1, z);
// Cover must have something solid below it
expect(below).to.not.equal(0);
}
}
}
}
});
});