test: cover distanceFromOrigin and locateOuterIsland
This commit is contained in:
1 parent
2d7a1a7264
commit
04c01edcbc
1 file changed
+156
@@ -0,0 +1,156 @@
|
||||
#include "testHarness.h"
|
||||
#include "vf/EndGen.h"
|
||||
|
||||
#include <cmath>
|
||||
#include <set>
|
||||
|
||||
using namespace vf;
|
||||
|
||||
namespace {
|
||||
|
||||
float distanceFromOrigin(int gx, int gz) {
|
||||
float x = static_cast<float>(gx);
|
||||
float z = static_cast<float>(gz);
|
||||
return std::sqrt(x * x + z * z);
|
||||
}
|
||||
|
||||
bool locateOuterIsland(const EndGenerator& generator, int& outX, int& outZ) {
|
||||
const EndGenerator::Params& params = generator.settings();
|
||||
for (int gx = params.outerDistance; gx < params.outerDistance + 2000; gx += 4) {
|
||||
for (int gz = -600; gz <= 600; gz += 4) {
|
||||
if (generator.biomeAt(gx, gz) != EndBiome::OuterIsland) continue;
|
||||
outX = gx;
|
||||
outZ = gz;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
int tallyBlocks(const World& world, Block block, int minX, int minZ, int span, int ceilingY) {
|
||||
int total = 0;
|
||||
for (int gx = minX; gx < minX + span; ++gx)
|
||||
for (int gz = minZ; gz < minZ + span; ++gz)
|
||||
for (int gy = 0; gy < ceilingY; ++gy)
|
||||
if (world.blockAt(gx, gy, gz) == block) ++total;
|
||||
return total;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
VF_TEST(endChunkGenerationRepeatsExactlyOnTheSameSeed) {
|
||||
EndGenerator generator;
|
||||
Chunk first, second;
|
||||
generator.generateChunk(first, {1, 3, -1});
|
||||
generator.generateChunk(second, {1, 3, -1});
|
||||
CHECK(first.raw() == second.raw());
|
||||
|
||||
EndGenerator::Params other;
|
||||
other.seed = 24601u;
|
||||
EndGenerator reseeded(other);
|
||||
Chunk different;
|
||||
reseeded.generateChunk(different, {1, 3, -1});
|
||||
CHECK(first.raw() != different.raw());
|
||||
}
|
||||
|
||||
VF_TEST(endColumnIsByteIdenticalAcrossTwoRuns) {
|
||||
EndGenerator generator;
|
||||
World first, second;
|
||||
generator.generateColumn(first, 2, -2);
|
||||
generator.generateColumn(second, 2, -2);
|
||||
|
||||
CHECK_EQ(first.chunkCount(), second.chunkCount());
|
||||
int mismatches = 0;
|
||||
for (const auto& entry : first.allChunks()) {
|
||||
const Chunk* twin = second.chunkAt(entry.first);
|
||||
if (!twin || twin->raw() != entry.second->raw()) ++mismatches;
|
||||
}
|
||||
CHECK_EQ(mismatches, 0);
|
||||
}
|
||||
|
||||
VF_TEST(endCentralIslandIsSurroundedByVoid) {
|
||||
EndGenerator generator;
|
||||
const EndGenerator::Params& params = generator.settings();
|
||||
|
||||
CHECK(!generator.isVoid(0, 0));
|
||||
CHECK_EQ(generator.biomeAt(0, 0), EndBiome::CentralIsland);
|
||||
|
||||
int solidNearCentre = 0;
|
||||
for (int gx = -40; gx <= 40; gx += 5)
|
||||
for (int gz = -40; gz <= 40; gz += 5)
|
||||
if (!generator.isVoid(gx, gz)) ++solidNearCentre;
|
||||
CHECK(solidNearCentre > 200);
|
||||
|
||||
int intruders = 0;
|
||||
int checkedRing = 0;
|
||||
for (int gx = -600; gx <= 600; gx += 9) {
|
||||
for (int gz = -600; gz <= 600; gz += 9) {
|
||||
float distance = distanceFromOrigin(gx, gz);
|
||||
if (distance <= params.centralRadius + params.edgeAmplitude) continue;
|
||||
if (distance >= static_cast<float>(params.outerDistance)) continue;
|
||||
++checkedRing;
|
||||
if (!generator.isVoid(gx, gz)) ++intruders;
|
||||
if (generator.biomeAt(gx, gz) != EndBiome::Void) ++intruders;
|
||||
if (generator.islandAt(gx, gz).valid()) ++intruders;
|
||||
}
|
||||
}
|
||||
CHECK(checkedRing > 1000);
|
||||
CHECK_EQ(intruders, 0);
|
||||
}
|
||||
|
||||
VF_TEST(endIslandEdgeIsRaggedNotACleanCircle) {
|
||||
EndGenerator generator;
|
||||
const EndGenerator::Params& params = generator.settings();
|
||||
|
||||
int inside = 0;
|
||||
int outside = 0;
|
||||
for (int step = 0; step < 360; step += 3) {
|
||||
float angle = 3.14159265f * static_cast<float>(step) / 180.0f;
|
||||
int gx = static_cast<int>(std::lround(std::cos(angle) * params.centralRadius));
|
||||
int gz = static_cast<int>(std::lround(std::sin(angle) * params.centralRadius));
|
||||
if (generator.isVoid(gx, gz)) ++outside;
|
||||
else ++inside;
|
||||
}
|
||||
CHECK(inside > 0);
|
||||
CHECK(outside > 0);
|
||||
}
|
||||
|
||||
VF_TEST(endTerrainIsEndStoneUnderAnEmptySky) {
|
||||
EndGenerator generator;
|
||||
World world;
|
||||
generator.generateColumn(world, 0, 0);
|
||||
|
||||
int surface = generator.surfaceHeight(8, 8);
|
||||
CHECK(surface > generator.settings().floorY);
|
||||
CHECK_EQ(world.blockAt(8, surface, 8), Block::EndStone);
|
||||
CHECK(generator.isStone(8, surface, 8));
|
||||
CHECK(!generator.isStone(8, surface + 1, 8));
|
||||
|
||||
int deepBottom = surface;
|
||||
while (generator.isStone(8, deepBottom - 1, 8)) --deepBottom;
|
||||
CHECK(deepBottom > generator.settings().floorY);
|
||||
CHECK_EQ(world.blockAt(8, deepBottom - 1, 8), Block::Air);
|
||||
CHECK_EQ(world.blockAt(8, 120, 8), Block::Air);
|
||||
}
|
||||
|
||||
VF_TEST(voidColumnsReportNoSurfaceAtAll) {
|
||||
EndGenerator generator;
|
||||
CHECK(generator.isVoid(300, 300));
|
||||
CHECK_EQ(generator.surfaceHeight(300, 300), generator.settings().floorY - 1);
|
||||
CHECK(!generator.isStone(300, 52, 300));
|
||||
CHECK_EQ(generator.biomeAt(300, 300), EndBiome::Void);
|
||||
|
||||
World world;
|
||||
generator.generateColumn(world, 20, 20);
|
||||
CHECK_EQ(tallyBlocks(world, Block::EndStone, 320, 320, 16, 128), 0);
|
||||
}
|
||||
|
||||
VF_TEST(obsidianPillarsRingTheCentreDeterministically) {
|
||||
EndGenerator generator;
|
||||
const EndGenerator::Params& params = generator.settings();
|
||||
std::vector<ObsidianPillar> ring = generator.pillars();
|
||||
std::vector<ObsidianPillar> again = generator.pillars();
|
||||
|
||||
CHECK_EQ(ring.size(), static_cast<std::size_t>(params.pillarCount));
|
||||
CHECK_EQ(again.size(), ring.size());
|
||||
|
||||
Reference in new issue
Block a user