test: cover testLoot
This commit is contained in:
1 parent
ea3d54436c
commit
80ef7386dc
1 file changed
+157
@@ -156,3 +156,160 @@ VF_TEST(fortuneMultipliesOreDropsAndNeverDropsBelowTheBaseYield) {
|
||||
CHECK_EQ(worstPlain, 1);
|
||||
CHECK_EQ(worstFortune, 1);
|
||||
|
||||
CHECK_EQ(maxOverSeeds(Block::DiamondOre, bare, ItemId::DiamondPickaxe, ItemId::DiamondGem, 400),
|
||||
1);
|
||||
CHECK_EQ(maxOverSeeds(Block::DiamondOre, fortune, ItemId::DiamondPickaxe, ItemId::DiamondGem,
|
||||
400),
|
||||
4);
|
||||
|
||||
// Silk Touch wins over Fortune: the ore block itself, never a multiplied gem.
|
||||
LootContext both = enchanted(ItemId::DiamondPickaxe, EnchantKind::SilkTouch, 1, 99u);
|
||||
addEnchant(both.toolEnchants, EnchantKind::Fortune, 3);
|
||||
LootRoll roll = rollBlockDrops(Block::DiamondOre, both);
|
||||
CHECK_EQ(roll.countOf(ItemId::DiamondOre), 1);
|
||||
CHECK_EQ(roll.countOf(ItemId::DiamondGem), 0);
|
||||
}
|
||||
|
||||
VF_TEST(grassYieldsDirtAndBedrockYieldsNothingAtAll) {
|
||||
LootContext shovel = contextWith(ItemId::IronShovel, 5u);
|
||||
LootRoll grass = rollBlockDrops(Block::Grass, shovel);
|
||||
CHECK_EQ(grass.countOf(ItemId::Dirt), 1);
|
||||
CHECK_EQ(grass.countOf(ItemId::Grass), 0);
|
||||
|
||||
LootContext pickaxe = contextWith(ItemId::DiamondPickaxe, 5u);
|
||||
CHECK(rollBlockDrops(Block::Bedrock, pickaxe).empty());
|
||||
CHECK(blockLootTable(Block::Bedrock).empty());
|
||||
|
||||
LootContext silk = enchanted(ItemId::DiamondPickaxe, EnchantKind::SilkTouch, 1, 5u);
|
||||
CHECK(rollBlockDrops(Block::Bedrock, silk).empty());
|
||||
}
|
||||
|
||||
VF_TEST(leavesOnlyDropTheirSubstituteCuttingWhenSilkTouchIsAbsent) {
|
||||
LootContext silk = enchanted(ItemId::IronHoe, EnchantKind::SilkTouch, 1, 3u);
|
||||
LootRoll harvested = rollBlockDrops(Block::Leaves, silk);
|
||||
CHECK_EQ(harvested.countOf(ItemId::Leaves), 1);
|
||||
CHECK_EQ(harvested.totalCount(), 1);
|
||||
|
||||
int cuttings = 0;
|
||||
int cuttingsWithFortune = 0;
|
||||
int leafBlocks = 0;
|
||||
EnchantSet fortune;
|
||||
addEnchant(fortune, EnchantKind::Fortune, 3);
|
||||
for (int i = 0; i < 1500; ++i) {
|
||||
LootContext plain = contextWith(ItemId::IronHoe, seedFor(i));
|
||||
LootRoll roll = rollBlockDrops(Block::Leaves, plain);
|
||||
cuttings += roll.countOf(ItemId::Wood);
|
||||
leafBlocks += roll.countOf(ItemId::Leaves);
|
||||
|
||||
LootContext lucky = contextWith(ItemId::IronHoe, seedFor(i));
|
||||
lucky.toolEnchants = fortune;
|
||||
cuttingsWithFortune += rollBlockDrops(Block::Leaves, lucky).countOf(ItemId::Wood);
|
||||
}
|
||||
CHECK_EQ(leafBlocks, 0);
|
||||
CHECK(cuttings > 0);
|
||||
CHECK(cuttingsWithFortune > cuttings * 2);
|
||||
}
|
||||
|
||||
VF_TEST(toolTierGatesTheOresTheWayTheHarvestLevelsSay) {
|
||||
CHECK(!toolQualifiesFor(Block::Stone, ItemId::None));
|
||||
CHECK(!toolQualifiesFor(Block::Stone, ItemId::IronAxe));
|
||||
CHECK(toolQualifiesFor(Block::Stone, ItemId::WoodPickaxe));
|
||||
|
||||
CHECK(!toolQualifiesFor(Block::IronOre, ItemId::WoodPickaxe));
|
||||
CHECK(!toolQualifiesFor(Block::IronOre, ItemId::GoldPickaxe));
|
||||
CHECK(toolQualifiesFor(Block::IronOre, ItemId::StonePickaxe));
|
||||
|
||||
CHECK(!toolQualifiesFor(Block::DiamondOre, ItemId::StonePickaxe));
|
||||
CHECK(!toolQualifiesFor(Block::DiamondOre, ItemId::GoldPickaxe));
|
||||
CHECK(toolQualifiesFor(Block::DiamondOre, ItemId::IronPickaxe));
|
||||
CHECK(toolQualifiesFor(Block::EmeraldOre, ItemId::DiamondPickaxe));
|
||||
|
||||
// Nothing outside the pickaxe class is gated at all.
|
||||
CHECK(toolQualifiesFor(Block::Dirt, ItemId::None));
|
||||
CHECK(toolQualifiesFor(Block::Leaves, ItemId::None));
|
||||
CHECK(toolQualifiesFor(Block::Grass, ItemId::WoodShovel));
|
||||
}
|
||||
|
||||
VF_TEST(aBlockBrokenWithTooWeakAToolProducesNoDropsAtAll) {
|
||||
LootContext weak = contextWith(ItemId::StonePickaxe, 11u);
|
||||
CHECK(rollBlockDrops(Block::DiamondOre, weak).empty());
|
||||
|
||||
LootContext bare = contextWith(ItemId::None, 11u);
|
||||
CHECK(rollBlockDrops(Block::Stone, bare).empty());
|
||||
|
||||
// The gate runs before the table, so even Silk Touch cannot rescue it.
|
||||
LootContext silkOnAStonePick = enchanted(ItemId::StonePickaxe, EnchantKind::SilkTouch, 1, 11u);
|
||||
CHECK(rollBlockDrops(Block::DiamondOre, silkOnAStonePick).empty());
|
||||
}
|
||||
|
||||
VF_TEST(zombiesDropFleshAlwaysAndIronOnlyWhenAPlayerLandedTheKill) {
|
||||
int ingotsFromPlayers = 0;
|
||||
int ingotsFromTheWorld = 0;
|
||||
int fleshTotal = 0;
|
||||
for (int i = 0; i < 3000; ++i) {
|
||||
LootRoll byPlayer = rollMobDrops(LootTable::MobKind::Zombie, killContext(true, seedFor(i)));
|
||||
LootRoll byWorld = rollMobDrops(LootTable::MobKind::Zombie, killContext(false, seedFor(i)));
|
||||
ingotsFromPlayers += byPlayer.countOf(ItemId::IronIngot);
|
||||
ingotsFromTheWorld += byWorld.countOf(ItemId::IronIngot);
|
||||
fleshTotal += byPlayer.countOf(ItemId::RottenFlesh);
|
||||
}
|
||||
CHECK_EQ(ingotsFromTheWorld, 0);
|
||||
CHECK(ingotsFromPlayers > 0);
|
||||
CHECK(fleshTotal > 2000);
|
||||
CHECK(fleshTotal < 4500);
|
||||
}
|
||||
|
||||
VF_TEST(lootingRaisesBothTheDropCeilingAndTheRareDropRate) {
|
||||
int plainCeiling = 0;
|
||||
int lootedCeiling = 0;
|
||||
int plainIngots = 0;
|
||||
int lootedIngots = 0;
|
||||
for (int i = 0; i < 3000; ++i) {
|
||||
LootContext plain = killContext(true, seedFor(i));
|
||||
LootContext looted = killContext(true, seedFor(i));
|
||||
addEnchant(looted.toolEnchants, EnchantKind::Looting, 3);
|
||||
|
||||
LootRoll plainRoll = rollMobDrops(LootTable::MobKind::Zombie, plain);
|
||||
LootRoll lootedRoll = rollMobDrops(LootTable::MobKind::Zombie, looted);
|
||||
plainCeiling = std::max(plainCeiling, plainRoll.countOf(ItemId::RottenFlesh));
|
||||
lootedCeiling = std::max(lootedCeiling, lootedRoll.countOf(ItemId::RottenFlesh));
|
||||
plainIngots += plainRoll.countOf(ItemId::IronIngot);
|
||||
lootedIngots += lootedRoll.countOf(ItemId::IronIngot);
|
||||
}
|
||||
CHECK_EQ(plainCeiling, 2);
|
||||
CHECK_EQ(lootedCeiling, 5);
|
||||
CHECK(lootedIngots > plainIngots);
|
||||
}
|
||||
|
||||
VF_TEST(livestockDropRawMeatThatComesOutCookedWhenTheKillWasFiery) {
|
||||
const struct { LootTable::MobKind kind; ItemId raw; ItemId cooked; int ceiling; } herd[] = {
|
||||
{LootTable::MobKind::Sheep, ItemId::RawMutton, ItemId::CookedMutton, 2},
|
||||
{LootTable::MobKind::Cow, ItemId::RawBeef, ItemId::CookedBeef, 3},
|
||||
{LootTable::MobKind::Pig, ItemId::RawPorkchop, ItemId::CookedPorkchop, 3},
|
||||
};
|
||||
for (const auto& animal : herd) {
|
||||
int rawSeen = 0;
|
||||
int cookedSeen = 0;
|
||||
int highest = 0;
|
||||
for (int i = 0; i < 300; ++i) {
|
||||
LootContext plain = killContext(true, seedFor(i));
|
||||
LootRoll rawRoll = rollMobDrops(animal.kind, plain);
|
||||
rawSeen += rawRoll.countOf(animal.raw);
|
||||
highest = std::max(highest, rawRoll.countOf(animal.raw));
|
||||
CHECK_EQ(rawRoll.countOf(animal.cooked), 0);
|
||||
|
||||
LootContext burning = killContext(true, seedFor(i));
|
||||
burning.fiery = true;
|
||||
LootRoll cookedRoll = rollMobDrops(animal.kind, burning);
|
||||
cookedSeen += cookedRoll.countOf(animal.cooked);
|
||||
CHECK_EQ(cookedRoll.countOf(animal.raw), 0);
|
||||
}
|
||||
CHECK_EQ(rawSeen, cookedSeen);
|
||||
CHECK_EQ(highest, animal.ceiling);
|
||||
}
|
||||
}
|
||||
|
||||
VF_TEST(lootContextForCarriesTheKillOverAndRefusesADeadSeed) {
|
||||
EnchantSet enchants;
|
||||
addEnchant(enchants, EnchantKind::Looting, 2);
|
||||
|
||||
Reference in new issue
Block a user