93 lines
3.1 KiB
C++
93 lines
3.1 KiB
C++
#include "testHarness.h"
|
|
#include "vf/Fluid.h"
|
|
|
|
using namespace vf;
|
|
|
|
namespace {
|
|
|
|
void solidLayer(World& world, int y, Vec3i lo, Vec3i hi) {
|
|
for (int x = lo.x; x <= hi.x; ++x)
|
|
for (int z = lo.z; z <= hi.z; ++z)
|
|
world.setBlock(x, y, z, Block::Stone);
|
|
}
|
|
|
|
uint8_t maxWater(const FluidSim& sim) {
|
|
uint8_t hi = 0;
|
|
for (uint8_t v : sim.levels()) hi = v > hi ? v : hi;
|
|
return hi;
|
|
}
|
|
|
|
} // namespace
|
|
|
|
VF_TEST(fluidSpreadsWithDecreasingLevelsSymmetrically) {
|
|
World world;
|
|
solidLayer(world, 0, {0, 0, 0}, {12, 0, 12});
|
|
FluidSim sim(world, {0, 0, 0}, {13, 3, 13});
|
|
sim.addSource(6, 1, 6);
|
|
int steps = sim.settle(50);
|
|
CHECK(steps < 50); // reaches a stable pool
|
|
|
|
CHECK_EQ(static_cast<int>(sim.level(6, 1, 6)), fluidMax);
|
|
CHECK_EQ(static_cast<int>(sim.level(7, 1, 6)), fluidMax - 1);
|
|
CHECK_EQ(static_cast<int>(sim.level(5, 1, 6)), fluidMax - 1); // symmetry -x
|
|
CHECK_EQ(static_cast<int>(sim.level(6, 1, 7)), fluidMax - 1); // symmetry +z
|
|
CHECK_EQ(static_cast<int>(sim.level(9, 1, 6)), fluidMax - 3);
|
|
CHECK_EQ(static_cast<int>(sim.level(10, 1, 10)), 0); // beyond reach
|
|
CHECK_EQ(static_cast<int>(sim.level(6, 2, 6)), 0); // pool stays one deep
|
|
}
|
|
|
|
VF_TEST(fluidFallsThroughHoleAndSpreadsBelow) {
|
|
World world;
|
|
solidLayer(world, 0, {0, 0, 0}, {12, 0, 12}); // lower floor
|
|
solidLayer(world, 4, {0, 4, 0}, {12, 4, 12}); // upper floor
|
|
world.setBlock(6, 4, 6, Block::Air); // hole in the upper floor
|
|
FluidSim sim(world, {0, 0, 0}, {13, 6, 13});
|
|
sim.addSource(3, 5, 6);
|
|
sim.settle(80);
|
|
|
|
CHECK_EQ(static_cast<int>(sim.level(6, 2, 6)), fluidMax); // falling column is full
|
|
CHECK_EQ(static_cast<int>(sim.level(6, 1, 6)), fluidMax); // landed on lower floor
|
|
CHECK(sim.level(7, 1, 6) > 0); // spreads across the lower floor
|
|
CHECK(sim.level(8, 1, 6) > 0);
|
|
}
|
|
|
|
VF_TEST(fluidDrainsAfterSourceRemoved) {
|
|
World world;
|
|
solidLayer(world, 0, {0, 0, 0}, {12, 0, 12});
|
|
FluidSim sim(world, {0, 0, 0}, {13, 3, 13});
|
|
sim.addSource(6, 1, 6);
|
|
sim.settle(50);
|
|
CHECK(maxWater(sim) == fluidMax);
|
|
|
|
sim.removeSource(6, 1, 6);
|
|
int steps = sim.settle(50);
|
|
CHECK(steps < 50);
|
|
CHECK_EQ(static_cast<int>(maxWater(sim)), 0); // pool fully drained
|
|
}
|
|
|
|
VF_TEST(fluidIsDeterministic) {
|
|
World worldA, worldB;
|
|
solidLayer(worldA, 0, {0, 0, 0}, {12, 0, 12});
|
|
solidLayer(worldB, 0, {0, 0, 0}, {12, 0, 12});
|
|
FluidSim a(worldA, {0, 0, 0}, {13, 3, 13});
|
|
FluidSim b(worldB, {0, 0, 0}, {13, 3, 13});
|
|
a.addSource(6, 1, 6);
|
|
b.addSource(6, 1, 6);
|
|
a.settle(50);
|
|
b.settle(50);
|
|
CHECK(a.levels() == b.levels());
|
|
}
|
|
|
|
VF_TEST(fluidBlockedBySolidWall) {
|
|
World world;
|
|
solidLayer(world, 0, {0, 0, 0}, {12, 0, 12});
|
|
for (int y = 1; y <= 2; ++y)
|
|
for (int z = 0; z <= 12; ++z)
|
|
world.setBlock(8, y, z, Block::Stone); // wall at x=8
|
|
FluidSim sim(world, {0, 0, 0}, {13, 3, 13});
|
|
sim.addSource(6, 1, 6);
|
|
sim.settle(50);
|
|
CHECK(sim.level(7, 1, 6) > 0); // wet up to the wall
|
|
CHECK_EQ(static_cast<int>(sim.level(9, 1, 6)), 0); // nothing past the wall
|
|
}
|