#include "testHarness.h" #include "vf/Climate.h" #include "vf/BiomeGen.h" using namespace vf; namespace { ClimateConfig coldConfig() { ClimateConfig cfg; cfg.freezeTemperature = 100.0f; cfg.meltTemperature = 200.0f; return cfg; } ClimateConfig warmConfig() { ClimateConfig cfg; cfg.freezeTemperature = -100.0f; cfg.meltTemperature = -100.0f; return cfg; } ClimateConfig neutralConfig() { ClimateConfig cfg; cfg.freezeTemperature = -100.0f; cfg.meltTemperature = 200.0f; return cfg; } } // namespace VF_TEST(temperatureFallsWithHeightAndLatitude) { BiomeGen biomes; Climate climate(biomes); float atSea = climate.temperatureAt(50, climate.settings().seaLevel, 0); float aloft = climate.temperatureAt(50, climate.settings().seaLevel + 80, 0); float polar = climate.temperatureAt(50, climate.settings().seaLevel, 4000); CHECK(aloft < atSea); CHECK(polar < atSea); } VF_TEST(exposedWaterFreezesWhenColdButCoveredWaterDoesNot) { BiomeGen biomes; Climate climate(biomes, coldConfig()); World world; world.setBlock(10, 30, 10, Block::Water); world.setBlock(14, 30, 10, Block::Water); world.setBlock(14, 31, 10, Block::Stone); std::vector changes = climate.tick(world, Vec3i{8, 30, 8}, Vec3i{10, 4, 6}, Precipitation::None); Climate::apply(world, changes); CHECK(world.blockAt(10, 30, 10) == Block::Ice); CHECK(world.blockAt(14, 30, 10) == Block::Water); } VF_TEST(iceThawsWhenWarm) { BiomeGen biomes; Climate climate(biomes, warmConfig()); World world; world.setBlock(5, 40, 5, Block::Ice); std::vector changes = climate.tick(world, Vec3i{4, 40, 4}, Vec3i{4, 2, 4}, Precipitation::None); Climate::apply(world, changes); CHECK(world.blockAt(5, 40, 5) == Block::Water); } VF_TEST(iceMeltsBesideHeatSourceOnlyWhenAdjacent) { BiomeGen biomes; Climate climate(biomes, neutralConfig()); World world; world.setBlock(20, 50, 20, Block::Ice); world.setBlock(21, 50, 20, Block::Lava); world.setBlock(25, 50, 20, Block::Ice); std::vector changes = climate.tick(world, Vec3i{18, 49, 18}, Vec3i{12, 4, 6}, Precipitation::None); Climate::apply(world, changes); CHECK(world.blockAt(20, 50, 20) == Block::Water); CHECK(world.blockAt(25, 50, 20) == Block::Ice); } VF_TEST(snowAccumulatesUnderSnowfallAndStopsWithoutIt) { BiomeGen biomes; Climate climate(biomes, coldConfig()); World world; world.setBlock(0, 30, 0, Block::Stone); Vec3i origin{-1, 30, -1}; Vec3i dims{3, 5, 3}; Vec3i snowCell{0, 31, 0}; std::vector first = climate.tick(world, origin, dims, Precipitation::Snow); Climate::apply(world, first); CHECK(world.blockAt(0, 31, 0) == Block::SnowLayer); CHECK_EQ(climate.snowDepthAt(snowCell), 1); for (int i = 0; i < 3; ++i) { std::vector more = climate.tick(world, origin, dims, Precipitation::Snow); Climate::apply(world, more); } CHECK_EQ(climate.snowDepthAt(snowCell), 4); int depthBefore = climate.snowDepthAt(snowCell); std::vector dry = climate.tick(world, origin, dims, Precipitation::None); Climate::apply(world, dry); CHECK_EQ(climate.snowDepthAt(snowCell), depthBefore); } VF_TEST(snowDepthClampsAtMax) { BiomeGen biomes; ClimateConfig cfg = coldConfig(); cfg.maxSnowDepth = 3; Climate climate(biomes, cfg); World world; world.setBlock(0, 30, 0, Block::Stone); Vec3i origin{-1, 30, -1}; Vec3i dims{3, 5, 3}; for (int i = 0; i < 10; ++i) { std::vector changes = climate.tick(world, origin, dims, Precipitation::Snow); Climate::apply(world, changes); } CHECK_EQ(climate.snowDepthAt(Vec3i{0, 31, 0}), 3); } VF_TEST(iceCompactsToPackedIceInProlongedCold) { BiomeGen biomes; ClimateConfig cfg = coldConfig(); cfg.packThreshold = 4; Climate climate(biomes, cfg); World world; world.setBlock(5, 40, 5, Block::Ice); Vec3i origin{4, 40, 4}; Vec3i dims{4, 3, 4}; for (int i = 0; i < 3; ++i) { std::vector changes = climate.tick(world, origin, dims, Precipitation::None); Climate::apply(world, changes); } CHECK(world.blockAt(5, 40, 5) == Block::Ice); CHECK_EQ(climate.iceAgeAt(Vec3i{5, 40, 5}), 3); std::vector last = climate.tick(world, origin, dims, Precipitation::None); Climate::apply(world, last); CHECK(world.blockAt(5, 40, 5) == Block::PackedIce); } VF_TEST(frostSpreadsFromExistingIceButNotAcrossOpenWater) { BiomeGen biomes; ClimateConfig cfg; cfg.freezeTemperature = -100.0f; cfg.frostSpreadTemperature = 100.0f; cfg.meltTemperature = 200.0f; Climate climate(biomes, cfg); World world; world.setBlock(10, 40, 10, Block::Ice); world.setBlock(11, 40, 10, Block::Water); world.setBlock(20, 40, 10, Block::Water); std::vector changes = climate.tick(world, Vec3i{8, 40, 8}, Vec3i{16, 3, 6}, Precipitation::None); Climate::apply(world, changes); CHECK(world.blockAt(11, 40, 10) == Block::Ice); CHECK(world.blockAt(20, 40, 10) == Block::Water); } VF_TEST(packedIceMeltsBesideHeat) { BiomeGen biomes; ClimateConfig cfg = coldConfig(); cfg.packThreshold = 2; Climate climate(biomes, cfg); World world; world.setBlock(5, 40, 5, Block::Ice); Vec3i origin{4, 40, 4}; Vec3i dims{4, 3, 4}; for (int i = 0; i < 2; ++i) { std::vector changes = climate.tick(world, origin, dims, Precipitation::None); Climate::apply(world, changes); } CHECK(world.blockAt(5, 40, 5) == Block::PackedIce); world.setBlock(6, 40, 5, Block::Lava); std::vector melt = climate.tick(world, origin, dims, Precipitation::None); Climate::apply(world, melt); CHECK(world.blockAt(5, 40, 5) == Block::Water); } VF_TEST(accumulatedSnowMeltsBesideHeat) { BiomeGen biomes; Climate climate(biomes, coldConfig()); World world; world.setBlock(0, 30, 0, Block::Stone); Vec3i origin{-1, 30, -1}; Vec3i dims{3, 5, 3}; Vec3i snowCell{0, 31, 0}; for (int i = 0; i < 5; ++i) { std::vector changes = climate.tick(world, origin, dims, Precipitation::Snow); Climate::apply(world, changes); } int peak = climate.snowDepthAt(snowCell); CHECK(peak > 1); world.setBlock(1, 31, 0, Block::Torch); for (int i = 0; i < peak; ++i) { std::vector changes = climate.tick(world, origin, dims, Precipitation::None); Climate::apply(world, changes); } CHECK_EQ(climate.snowDepthAt(snowCell), 0); CHECK(world.blockAt(0, 31, 0) == Block::Air); }