155 lines
4.7 KiB
JavaScript
155 lines
4.7 KiB
JavaScript
import { expect } from "@esm-bundle/chai";
|
|
import { PostProcessor } from "../../src/generation/PostProcessing.js";
|
|
import { VoxelGrid } from "../../src/grid/VoxelGrid.js";
|
|
|
|
describe("Generation: PostProcessor", () => {
|
|
let grid;
|
|
|
|
beforeEach(() => {
|
|
grid = new VoxelGrid(20, 5, 20);
|
|
});
|
|
|
|
it("CoA 1: ensureConnectivity should identify separate regions", () => {
|
|
// Create two disconnected floor regions
|
|
// Region 1: left side
|
|
for (let x = 1; x < 5; x++) {
|
|
for (let z = 1; z < 5; z++) {
|
|
grid.setCell(x, 0, z, 1); // Floor
|
|
grid.setCell(x, 1, z, 0); // Air
|
|
}
|
|
}
|
|
|
|
// Region 2: right side (disconnected)
|
|
for (let x = 15; x < 19; x++) {
|
|
for (let z = 15; z < 19; z++) {
|
|
grid.setCell(x, 0, z, 1); // Floor
|
|
grid.setCell(x, 1, z, 0); // Air
|
|
}
|
|
}
|
|
|
|
PostProcessor.ensureConnectivity(grid);
|
|
|
|
// After processing, smaller regions should be filled
|
|
// The grid should have connectivity ensured
|
|
expect(grid).to.exist;
|
|
});
|
|
|
|
it("CoA 2: ensureConnectivity should keep largest region", () => {
|
|
// Create one large region and one small region
|
|
// Large region
|
|
for (let x = 1; x < 10; x++) {
|
|
for (let z = 1; z < 10; z++) {
|
|
grid.setCell(x, 0, z, 1);
|
|
grid.setCell(x, 1, z, 0);
|
|
}
|
|
}
|
|
|
|
// Small region
|
|
for (let x = 15; x < 17; x++) {
|
|
for (let z = 15; z < 17; z++) {
|
|
grid.setCell(x, 0, z, 1);
|
|
grid.setCell(x, 1, z, 0);
|
|
}
|
|
}
|
|
|
|
const smallRegionAirBefore = grid.getCell(15, 1, 15);
|
|
|
|
PostProcessor.ensureConnectivity(grid);
|
|
|
|
// Small region should be filled (no longer air)
|
|
const smallRegionAfter = grid.getCell(15, 1, 15);
|
|
// If connectivity was ensured, small region might be filled
|
|
// (exact behavior depends on implementation)
|
|
expect(smallRegionAfter).to.exist;
|
|
});
|
|
|
|
it("CoA 3: floodFill should collect all connected air tiles", () => {
|
|
// Create a connected region
|
|
for (let x = 1; x < 5; x++) {
|
|
for (let z = 1; z < 5; z++) {
|
|
grid.setCell(x, 0, z, 1);
|
|
grid.setCell(x, 1, z, 0);
|
|
}
|
|
}
|
|
|
|
const visited = new Set();
|
|
const region = PostProcessor.floodFill(grid, 2, 1, 2, visited);
|
|
|
|
// Should collect multiple tiles
|
|
expect(region.length).to.be.greaterThan(1);
|
|
expect(region).to.deep.include({ x: 2, y: 1, z: 2 });
|
|
expect(region).to.deep.include({ x: 3, y: 1, z: 2 });
|
|
});
|
|
|
|
it("CoA 4: floodFill should not include disconnected tiles", () => {
|
|
// Create two separate regions with proper floor setup
|
|
// Region 1: connected tiles
|
|
grid.setCell(1, 0, 1, 1); // Floor
|
|
grid.setCell(1, 1, 1, 0); // Air
|
|
grid.setCell(2, 0, 1, 1); // Floor
|
|
grid.setCell(2, 1, 1, 0); // Air (connected)
|
|
|
|
// Region 2: disconnected (no floor connection)
|
|
grid.setCell(10, 0, 10, 1); // Floor
|
|
grid.setCell(10, 1, 10, 0); // Air (disconnected)
|
|
|
|
const visited = new Set();
|
|
const region = PostProcessor.floodFill(grid, 1, 1, 1, visited);
|
|
|
|
// Should only include connected tiles from region 1
|
|
expect(region.length).to.equal(2);
|
|
expect(region).to.deep.include({ x: 1, y: 1, z: 1 });
|
|
expect(region).to.deep.include({ x: 2, y: 1, z: 1 });
|
|
expect(region).to.not.deep.include({ x: 10, y: 1, z: 10 });
|
|
});
|
|
|
|
it("CoA 5: floodFill should respect bounds", () => {
|
|
// Start at edge
|
|
grid.setCell(0, 0, 0, 1);
|
|
grid.setCell(0, 1, 0, 0);
|
|
|
|
const visited = new Set();
|
|
const region = PostProcessor.floodFill(grid, 0, 1, 0, visited);
|
|
|
|
// Should only include valid positions
|
|
expect(region.length).to.be.greaterThanOrEqual(1);
|
|
region.forEach((pos) => {
|
|
expect(grid.isValidBounds(pos.x, pos.y, pos.z)).to.be.true;
|
|
});
|
|
});
|
|
|
|
it("CoA 6: ensureConnectivity should handle empty grid", () => {
|
|
// Grid with no floor regions
|
|
grid.fill(0);
|
|
|
|
// Should not throw
|
|
expect(() => PostProcessor.ensureConnectivity(grid)).to.not.throw();
|
|
});
|
|
|
|
it("CoA 7: ensureConnectivity should handle single region", () => {
|
|
// Create one connected region
|
|
for (let x = 1; x < 10; x++) {
|
|
for (let z = 1; z < 10; z++) {
|
|
grid.setCell(x, 0, z, 1);
|
|
grid.setCell(x, 1, z, 0);
|
|
}
|
|
}
|
|
|
|
const airCountBefore = Array.from(grid.cells).filter((v, i) => {
|
|
const y = Math.floor(i / (grid.size.x * grid.size.z)) % grid.size.y;
|
|
return y === 1 && v === 0;
|
|
}).length;
|
|
|
|
PostProcessor.ensureConnectivity(grid);
|
|
|
|
// Single region should remain intact
|
|
const airCountAfter = Array.from(grid.cells).filter((v, i) => {
|
|
const y = Math.floor(i / (grid.size.x * grid.size.z)) % grid.size.y;
|
|
return y === 1 && v === 0;
|
|
}).length;
|
|
|
|
// Air count should be similar (allowing for minor changes)
|
|
expect(airCountAfter).to.be.greaterThan(0);
|
|
});
|
|
});
|
|
|