From 8a6afca7f357e792c5de849a8533012ddd816383 Mon Sep 17 00:00:00 2001 From: DualFroz Date: Thu, 10 Sep 2026 21:16:59 +0200 Subject: [PATCH] test: add more cases for testBoss --- tests/testBoss.cpp | 81 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 81 insertions(+) diff --git a/tests/testBoss.cpp b/tests/testBoss.cpp index 4fca886..e76e96f 100644 --- a/tests/testBoss.cpp +++ b/tests/testBoss.cpp @@ -474,3 +474,84 @@ VF_TEST(theWitherDiesWhenItsHealthRunsOutAndStopsTicking) { WitherFight fight(66u, quickSummon(3)); fight.begin(Vec3{0.0f, 64.0f, 0.0f}); + std::vector targets; + targets.push_back(WitherTarget{Vec3{10.0f, 64.0f, 0.0f}, 500.0f, true}); + runUpToRangedPhase(fight, targets); + + std::vector execution; + execution.push_back(WitherHit{fight.settings().maxHealth, false}); + BossTickReport killed = fight.tick(execution, targets); + + CHECK(killed.defeated); + CHECK(killed.phase == BossPhase::Defeated); + CHECK(!fight.state().alive); + CHECK(!fight.state().bar.visible); + CHECK_NEAR(fight.state().health, 0.0f, 1e-6f); + + int attacksAtDeath = fight.state().attacksLaunched; + float targetHealth = targets[0].health; + for (int step = 0; step < 50; ++step) fight.tick(execution, targets); + CHECK_EQ(fight.state().attacksLaunched, attacksAtDeath); + CHECK_NEAR(targets[0].health, targetHealth, 1e-6f); +} + +VF_TEST(twoWitherFightsOnTheSameSeedAndScriptRunIdentically) { + auto playOut = [](std::vector& healthTrack, std::vector& targetTrack, + std::vector& minionSpots) { + WitherFight fight(0xbeefu, quickSummon(4)); + fight.begin(Vec3{0.0f, 64.0f, 0.0f}); + + std::vector targets; + targets.push_back(WitherTarget{Vec3{14.0f, 64.0f, 0.0f}, 100000.0f, true}); + targets.push_back(WitherTarget{Vec3{-30.0f, 64.0f, 8.0f}, 100000.0f, true}); + + for (int step = 0; step < 500; ++step) { + std::vector incoming; + if (step % 7 == 0) incoming.push_back(WitherHit{2.5f, step % 14 == 0}); + BossTickReport report = fight.tick(incoming, targets); + healthTrack.push_back(report.bossHealth); + targetTrack.push_back(targets[0].health); + } + for (const BossMinion& minion : fight.minions()) minionSpots.push_back(minion.position); + }; + + std::vector firstHealth; + std::vector firstTargets; + std::vector firstMinions; + std::vector secondHealth; + std::vector secondTargets; + std::vector secondMinions; + playOut(firstHealth, firstTargets, firstMinions); + playOut(secondHealth, secondTargets, secondMinions); + + CHECK_EQ(firstHealth.size(), secondHealth.size()); + for (std::size_t i = 0; i < firstHealth.size() && i < secondHealth.size(); ++i) { + CHECK_NEAR(firstHealth[i], secondHealth[i], 1e-6f); + CHECK_NEAR(firstTargets[i], secondTargets[i], 1e-6f); + } + CHECK(!firstMinions.empty()); + CHECK_EQ(firstMinions.size(), secondMinions.size()); + for (std::size_t i = 0; i < firstMinions.size() && i < secondMinions.size(); ++i) { + CHECK_NEAR(firstMinions[i].x, secondMinions[i].x, 1e-6f); + CHECK_NEAR(firstMinions[i].z, secondMinions[i].z, 1e-6f); + } +} + +VF_TEST(bothBossesAreDrivenByAValidBehaviourTree) { + EndGenerator end; + DragonFight dragon(end, 1u); + CHECK(dragon.brain().structureValid()); + CHECK(dragon.brain().stats().nodeCount > 10); + CHECK(dragon.brain().stats().depth <= maxBehaviorDepth); + CHECK_EQ(dragon.brain().root()->name(), std::string("dragonRoot")); + + WitherFight wither(2u); + CHECK(wither.brain().structureValid()); + CHECK(wither.brain().stats().nodeCount > 10); + CHECK(wither.brain().stats().depth <= maxBehaviorDepth); + CHECK_EQ(wither.brain().root()->name(), std::string("witherRoot")); + + dragon.tick(clingingTo(dragon, 0.0f)); + CHECK_EQ(dragon.context().tick, 1); + CHECK_EQ(dragon.brain().tickCount(), 1); +}