test: extend coverage of testTrade

This commit is contained in:
dualfroz committed 2026-09-13 21:30:05 +02:00
1 parent f2782c8ffb
commit 76ca8e86f9
1 file changed
+100
+100
View File
@@ -313,3 +313,103 @@ VF_TEST(aCompletedTradeMovesBothSidesAndFeedsTheVillagerExperience) {
Container wallet = makeWallet(40); Container wallet = makeWallet(40);
TradeSession session(villager, offers, wallet); TradeSession session(villager, offers, wallet);
int lapisOffer = 1;
CHECK(offers.at(lapisOffer).output == ItemId::LapisLazuli);
int price = session.priceOf(lapisOffer);
TradeResult outcome = session.trade(lapisOffer);
CHECK(outcome.success);
CHECK(outcome.reason == TradeResult::Reason::Ok);
CHECK_EQ(outcome.pricePaid, price);
CHECK_EQ(outcome.secondaryPaid, 0);
CHECK_EQ(stockOf(wallet, ItemId::EmeraldGem), 40 - price);
CHECK_EQ(stockOf(wallet, ItemId::LapisLazuli), outcome.receivedCount);
CHECK_EQ(villager.experience, outcome.experienceGained);
CHECK_EQ(villager.gossip.valueOf(GossipKind::Trading), gossipTradingGain);
CHECK_EQ(session.tradesCompleted(), 1);
CHECK_EQ(session.emeraldsSpent(), price);
bool sawLevelUp = false;
for (int i = 0; i < 12 && session.available(lapisOffer); ++i)
if (session.trade(lapisOffer).leveledUp) sawLevelUp = true;
CHECK(sawLevelUp);
CHECK_EQ(villager.level, 2);
CHECK(villager.gossip.valueOf(GossipKind::Trading) > gossipTradingGain);
}
VF_TEST(secondaryInputIsRequiredAndConsumedByTheTrade) {
Villager villager = makeVillager(2, {0.5f, static_cast<float>(walkY), 0.5f}, 5u);
villager.profession = VillagerProfession::Cartographer;
villager.level = 2;
TradeOfferList offers = buildTradeOffers(VillagerProfession::Cartographer, 3u);
Container wallet = makeWallet(60);
TradeSession session(villager, offers, wallet);
int chestOffer = 3;
CHECK(offers.at(chestOffer).output == ItemId::Chest);
CHECK(offers.at(chestOffer).hasSecondaryInput());
CHECK(offers.at(chestOffer).inputB == ItemId::GoldIngot);
CHECK(!session.canAfford(chestOffer));
CHECK(session.trade(chestOffer).reason == TradeResult::Reason::MissingInputB);
wallet.insert(ItemId::GoldIngot, 3);
CHECK(session.canAfford(chestOffer));
int price = session.priceOf(chestOffer);
TradeResult outcome = session.trade(chestOffer);
CHECK(outcome.success);
CHECK_EQ(outcome.secondaryPaid, offers.at(chestOffer).inputBCount);
CHECK_EQ(stockOf(wallet, ItemId::GoldIngot), 3 - offers.at(chestOffer).inputBCount);
CHECK_EQ(stockOf(wallet, ItemId::EmeraldGem), 60 - price);
CHECK_EQ(stockOf(wallet, ItemId::Chest), outcome.receivedCount);
}
VF_TEST(sellingToTheVillagerTakesGoodsAndPaysOutEmeralds) {
Villager villager = makeLibrarian(1);
TradeOfferList offers = buildTradeOffers(VillagerProfession::Librarian, 1u);
Container wallet(27);
int planksOffer = 0;
CHECK(offers.at(planksOffer).inputA == ItemId::Planks);
CHECK(offers.at(planksOffer).output == ItemId::EmeraldGem);
TradeSession session(villager, offers, wallet);
CHECK(session.trade(planksOffer).reason == TradeResult::Reason::MissingInputA);
int price = session.priceOf(planksOffer);
wallet.insert(ItemId::Planks, price * 2);
TradeResult outcome = session.trade(planksOffer);
CHECK(outcome.success);
CHECK_EQ(stockOf(wallet, ItemId::Planks), price);
CHECK_EQ(stockOf(wallet, ItemId::EmeraldGem), outcome.receivedCount);
CHECK_EQ(session.emeraldsSpent(), 0);
}
VF_TEST(tradingLeavesGossipAndAStrongReputationCutsThePrice) {
Villager villager = makeLibrarian(villagerMaxLevel);
TradeOfferList offers = buildTradeOffers(VillagerProfession::Librarian, 1u);
Container wallet = makeWallet(400);
TradeSession session(villager, offers, wallet);
int diamondOffer = 7;
CHECK(offers.at(diamondOffer).tier == TradeTier::Master);
CHECK(offers.at(diamondOffer).output == ItemId::DiamondGem);
for (int i = 0; i < 2; ++i) CHECK(session.trade(diamondOffer).success);
CHECK_EQ(villager.gossip.valueOf(GossipKind::Trading), gossipTradingGain * 2);
restockOffers(offers);
CHECK_EQ(offers.at(diamondOffer).demand, 0);
session.refreshPrices(buildReputation(villager.gossip, {}), 0);
int politePrice = session.priceOf(diamondOffer);
CHECK_EQ(politePrice, offers.at(diamondOffer).basePrice());
villager.gossip.add(GossipKind::MajorPositive, gossipMajorPositiveGain);
ReputationView heroic = buildReputation(villager.gossip, {});
CHECK_EQ(heroic.discountPercent(), 10);
session.refreshPrices(heroic, 0);
CHECK(session.priceOf(diamondOffer) < politePrice);
session.refreshPrices(heroic, 3);
CHECK_EQ(session.priceModifier().totalPercent(), 90);
CHECK_EQ(session.priceOf(diamondOffer), 1);
}