test: strengthen tests for testLootTables
This commit is contained in:
1 parent
d87424e3c4
commit
bb66cdf90f
1 file changed
+170
@@ -643,3 +643,173 @@ VF_TEST(fishingSplitsIntoThreePoolsAndLuckShiftsTheWeightsAwayFromJunk) {
|
|||||||
CHECK_EQ(junkAtHighLuck, 0);
|
CHECK_EQ(junkAtHighLuck, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
VF_TEST(everyFishingPoolHandsBackSomethingFromItsOwnTable) {
|
||||||
|
const LootRegistry& registry = lootRegistry();
|
||||||
|
int emptyCatches = 0;
|
||||||
|
int strayItems = 0;
|
||||||
|
for (int i = 0; i < 2000; ++i) {
|
||||||
|
FishingLoot outcome = registry.rollFishing(
|
||||||
|
enchantedWith(ItemId::WoodHoe, EnchantKind::Fortune, 2, seedFor(i)));
|
||||||
|
if (outcome.caught.empty()) ++emptyCatches;
|
||||||
|
|
||||||
|
const LootTable& table = registry.tableFor(LootTableId::ofFishing(outcome.pool));
|
||||||
|
for (const ItemSlot& stack : outcome.caught.items) {
|
||||||
|
if (!poolCanYield(table.pools[0], stack.item)) ++strayItems;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
CHECK_EQ(emptyCatches, 0);
|
||||||
|
CHECK_EQ(strayItems, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
VF_TEST(lureShortensTheWaitAndTheWaitNeverFallsThroughItsFloor) {
|
||||||
|
const LootRegistry& registry = lootRegistry();
|
||||||
|
int plainTotal = 0;
|
||||||
|
int luredTotal = 0;
|
||||||
|
int belowFloor = 0;
|
||||||
|
int aboveCeiling = 0;
|
||||||
|
|
||||||
|
for (int i = 0; i < 1500; ++i) {
|
||||||
|
FishingLoot plain = registry.rollFishing(contextWith(ItemId::WoodHoe, seedFor(i)));
|
||||||
|
FishingLoot lured = registry.rollFishing(
|
||||||
|
enchantedWith(ItemId::WoodHoe, EnchantKind::Efficiency, 3, seedFor(i)));
|
||||||
|
plainTotal += plain.waitTicks;
|
||||||
|
luredTotal += lured.waitTicks;
|
||||||
|
|
||||||
|
if (plain.waitTicks < fishingMinWaitTicks) ++belowFloor;
|
||||||
|
if (plain.waitTicks > fishingBaseWaitTicks) ++aboveCeiling;
|
||||||
|
if (lured.waitTicks < fishingMinWaitTicks / 2) ++belowFloor;
|
||||||
|
if (lured.waitTicks > plain.waitTicks) ++aboveCeiling;
|
||||||
|
}
|
||||||
|
CHECK_EQ(belowFloor, 0);
|
||||||
|
CHECK_EQ(aboveCeiling, 0);
|
||||||
|
CHECK(luredTotal < plainTotal);
|
||||||
|
|
||||||
|
FishingLoot drowned = registry.rollFishing(
|
||||||
|
enchantedWith(ItemId::WoodHoe, EnchantKind::Efficiency, 5, seedFor(3)));
|
||||||
|
CHECK_EQ(drowned.waitTicks, fishingMinWaitTicks / 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
VF_TEST(fishingIsFullyDeterministicForAGivenSeedAndRod) {
|
||||||
|
const LootRegistry& registry = lootRegistry();
|
||||||
|
for (int i = 0; i < 200; ++i) {
|
||||||
|
LootContext context = enchantedWith(ItemId::WoodHoe, EnchantKind::Fortune, 2, seedFor(i));
|
||||||
|
FishingLoot first = registry.rollFishing(context);
|
||||||
|
FishingLoot second = registry.rollFishing(context);
|
||||||
|
CHECK_EQ(first.pool, second.pool);
|
||||||
|
CHECK_EQ(first.waitTicks, second.waitTicks);
|
||||||
|
CHECK(sameRoll(first.caught, second.caught));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
VF_TEST(lootTableHandlesRoundTripForEveryDomainAndRejectStaleIndices) {
|
||||||
|
const LootRegistry& registry = lootRegistry();
|
||||||
|
|
||||||
|
LootTableId stone = LootTableId::ofBlock(Block::Stone);
|
||||||
|
CHECK_EQ(stone.domain, LootTableId::Domain::Block);
|
||||||
|
CHECK_EQ(stone.index, static_cast<uint16_t>(Block::Stone));
|
||||||
|
CHECK(stone.valid());
|
||||||
|
CHECK(stone == LootTableId::ofBlock(Block::Stone));
|
||||||
|
CHECK(stone != LootTableId::ofBlock(Block::Dirt));
|
||||||
|
|
||||||
|
CHECK(LootTableId::ofMob(Species::Creeper).valid());
|
||||||
|
CHECK(LootTableId::ofChest(Structure::EndShip).valid());
|
||||||
|
CHECK(LootTableId::ofFishing(FishingLoot::Pool::Treasure).valid());
|
||||||
|
|
||||||
|
CHECK(!LootTableId::ofBlock(Block::Count).valid());
|
||||||
|
CHECK(!LootTableId::ofMob(Species::Count).valid());
|
||||||
|
CHECK(!LootTableId::ofChest(Structure::Count).valid());
|
||||||
|
CHECK(!LootTableId::ofFishing(FishingLoot::Pool::Count).valid());
|
||||||
|
|
||||||
|
LootTableId stale;
|
||||||
|
stale.domain = LootTableId::Domain::Block;
|
||||||
|
stale.index = 60000;
|
||||||
|
CHECK(!stale.valid());
|
||||||
|
CHECK(registry.tableFor(stale).empty());
|
||||||
|
|
||||||
|
LootTableId noDomain;
|
||||||
|
noDomain.domain = LootTableId::Domain::Count;
|
||||||
|
CHECK(!noDomain.valid());
|
||||||
|
CHECK(registry.tableFor(noDomain).empty());
|
||||||
|
}
|
||||||
|
|
||||||
|
VF_TEST(aTableFetchedByHandleRollsIdenticallyToTheRegistryShortcut) {
|
||||||
|
const LootRegistry& registry = lootRegistry();
|
||||||
|
|
||||||
|
for (Block block : {Block::Stone, Block::DiamondOre, Block::Grass, Block::Bookshelf}) {
|
||||||
|
LootContext context = contextWith(bestToolFor(registry.blockRule(block).harvestTool), 909u);
|
||||||
|
LootRoll viaHandle = rollLootTable(registry.tableFor(LootTableId::ofBlock(block)), context);
|
||||||
|
CHECK(sameRoll(viaHandle, registry.rollBlock(block, context)));
|
||||||
|
}
|
||||||
|
|
||||||
|
for (Species species : {Species::Zombie, Species::Witch, Species::Cow}) {
|
||||||
|
LootContext context = contextWith(ItemId::IronSword, 1717u);
|
||||||
|
context.playerKill = true;
|
||||||
|
LootRoll viaHandle = rollLootTable(registry.tableFor(LootTableId::ofMob(species)), context);
|
||||||
|
CHECK(sameRoll(viaHandle, registry.rollMob(species, context)));
|
||||||
|
}
|
||||||
|
|
||||||
|
for (Structure structure : {Structure::Temple, Structure::NetherFortress}) {
|
||||||
|
LootContext context = contextWith(ItemId::None, 31337u);
|
||||||
|
LootRoll viaHandle = rollLootTable(registry.tableFor(LootTableId::ofChest(structure)),
|
||||||
|
context);
|
||||||
|
CHECK(sameRoll(viaHandle, registry.rollChest(structure, context)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
VF_TEST(ruleToTableConversionBuildsExactlyThePoolsTheRuleDescribes) {
|
||||||
|
const LootRegistry& registry = lootRegistry();
|
||||||
|
|
||||||
|
LootTable stone = blockRuleTable(registry.blockRule(Block::Stone));
|
||||||
|
CHECK_EQ(stone.pools.size(), std::size_t{3});
|
||||||
|
CHECK_EQ(firstEntryOfPool(stone, 0), ItemId::Stone);
|
||||||
|
CHECK_EQ(firstEntryOfPool(stone, 1), ItemId::Cobblestone);
|
||||||
|
CHECK_EQ(firstEntryOfPool(stone, 2), ItemId::Stone);
|
||||||
|
CHECK_EQ(stone.pools[0].entries[0].conditions, LootEntry::SilkTouched);
|
||||||
|
CHECK_EQ(stone.pools[1].entries[0].conditions,
|
||||||
|
LootEntry::NotSilkTouched | LootEntry::NotFiery);
|
||||||
|
CHECK_EQ(stone.pools[2].entries[0].conditions, LootEntry::NotSilkTouched | LootEntry::Fiery);
|
||||||
|
|
||||||
|
LootTable leaves = blockRuleTable(registry.blockRule(Block::Leaves));
|
||||||
|
CHECK_EQ(leaves.pools.size(), std::size_t{3});
|
||||||
|
CHECK_EQ(firstEntryOfPool(leaves, 1), ItemId::Wood);
|
||||||
|
CHECK_EQ(leaves.pools[1].entries[0].functions, LootEntry::ChanceFortune);
|
||||||
|
CHECK_EQ(firstEntryOfPool(leaves, 2), ItemId::Stick);
|
||||||
|
|
||||||
|
LootTable lapis = blockRuleTable(registry.blockRule(Block::LapisOre));
|
||||||
|
CHECK_EQ(lapis.pools.size(), std::size_t{2});
|
||||||
|
CHECK_EQ(lapis.pools[1].entries[0].functions, LootEntry::CountRange | LootEntry::OreFortune);
|
||||||
|
|
||||||
|
CHECK(blockRuleTable(registry.blockRule(Block::Air)).empty());
|
||||||
|
|
||||||
|
LootTable cow = mobRuleTable(registry.mobRule(Species::Cow));
|
||||||
|
CHECK_EQ(cow.pools.size(), std::size_t{2});
|
||||||
|
CHECK_EQ(firstEntryOfPool(cow, 0), ItemId::RawBeef);
|
||||||
|
CHECK_EQ(firstEntryOfPool(cow, 1), ItemId::CookedBeef);
|
||||||
|
CHECK_EQ(cow.pools[0].entries[0].conditions, LootEntry::NotFiery);
|
||||||
|
CHECK_EQ(cow.pools[1].entries[0].conditions, LootEntry::Fiery);
|
||||||
|
|
||||||
|
LootTable zombie = mobRuleTable(registry.mobRule(Species::Zombie));
|
||||||
|
CHECK_EQ(zombie.pools.size(), std::size_t{2});
|
||||||
|
CHECK_EQ(zombie.pools[1].entries[0].conditions, LootEntry::PlayerKill);
|
||||||
|
CHECK_EQ(zombie.pools[1].entries[0].functions, LootEntry::ChanceLooting);
|
||||||
|
}
|
||||||
|
|
||||||
|
VF_TEST(theSharedRegistryIsBuiltOnceAndAlwaysHandsBackTheSameTables) {
|
||||||
|
CHECK(&lootRegistry() == &lootRegistry());
|
||||||
|
const LootRegistry& registry = lootRegistry();
|
||||||
|
CHECK(®istry.blockRule(Block::Stone) == ®istry.blockRule(Block::Stone));
|
||||||
|
CHECK(®istry.tableFor(LootTableId::ofBlock(Block::Stone)) ==
|
||||||
|
®istry.tableFor(LootTableId::ofBlock(Block::Stone)));
|
||||||
|
|
||||||
|
LootRegistry rebuilt;
|
||||||
|
CHECK(rebuilt.coversEveryBlock());
|
||||||
|
int divergences = 0;
|
||||||
|
for (int index = 0; index < static_cast<int>(Block::Count); ++index) {
|
||||||
|
Block block = static_cast<Block>(index);
|
||||||
|
LootContext context = contextWith(ItemId::DiamondPickaxe, seedFor(index));
|
||||||
|
if (!sameRoll(rebuilt.rollBlock(block, context), registry.rollBlock(block, context))) {
|
||||||
|
++divergences;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
CHECK_EQ(divergences, 0);
|
||||||
|
}
|
||||||
Reference in new issue
Block a user