#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(sim.level(6, 1, 6)), fluidMax); CHECK_EQ(static_cast(sim.level(7, 1, 6)), fluidMax - 1); CHECK_EQ(static_cast(sim.level(5, 1, 6)), fluidMax - 1); // symmetry -x CHECK_EQ(static_cast(sim.level(6, 1, 7)), fluidMax - 1); // symmetry +z CHECK_EQ(static_cast(sim.level(9, 1, 6)), fluidMax - 3); CHECK_EQ(static_cast(sim.level(10, 1, 10)), 0); // beyond reach CHECK_EQ(static_cast(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(sim.level(6, 2, 6)), fluidMax); // falling column is full CHECK_EQ(static_cast(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(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(sim.level(9, 1, 6)), 0); // nothing past the wall }