diff --git a/tests/testVillager.cpp b/tests/testVillager.cpp index 820e5ac..b0234b6 100644 --- a/tests/testVillager.cpp +++ b/tests/testVillager.cpp @@ -315,3 +315,117 @@ VF_TEST(deathReleasesTheBedAndWorkstationForSomebodyElse) { CHECK(heir.profession == VillagerProfession::Librarian); } +VF_TEST(neighboursStandingTogetherTradeGossipBothWays) { + Villager first = makeWorker(1, 0, 0, 61u); + Villager second = makeWorker(2, 1, 0, 62u); + Villager distant = makeWorker(3, 15, 0, 63u); + + first.gossip.add(GossipKind::MinorNegative, gossipMinorNegativeGain * 4); + second.gossip.add(GossipKind::Trading, gossipTradingGain * 6); + + CHECK(exchangeVillagerGossip(first, second)); + CHECK(second.gossip.valueOf(GossipKind::MinorNegative) > 0); + CHECK(first.gossip.valueOf(GossipKind::Trading) > 0); + + CHECK(!exchangeVillagerGossip(first, distant)); + CHECK_EQ(distant.gossip.valueOf(GossipKind::MinorNegative), 0); + + std::vector crowd{first, second, distant}; + CHECK_EQ(spreadVillageGossip(crowd), 1); + CHECK_EQ(crowd[2].gossip.valueOf(GossipKind::MinorNegative), 0); + + crowd[2].body.position = {1.5f, static_cast(walkY), 0.5f}; + CHECK(spreadVillageGossip(crowd) >= 2); + CHECK(crowd[2].gossip.valueOf(GossipKind::MinorNegative) > 0); + CHECK(crowd[2].gossip.valueOf(GossipKind::MinorNegative) <= + gossipTuning(GossipKind::MinorNegative).shareCap); +} + +VF_TEST(censusCountsBedsWorkstationsAndFoodAndGatesVillageGrowth) { + World world = makeVillage(); + PoiRegistry pois; + pois.scan(world, villageCenter, 12, 4); + + std::vector villagers{makeWorker(1, 1, 1, 71u), makeWorker(2, 2, 1, 72u)}; + VillageCensus empty = takeVillageCensus(villagers, pois, villageCenter, 12); + CHECK_EQ(empty.villagers, 2); + CHECK_EQ(empty.living, 2); + CHECK_EQ(empty.beds, 2); + CHECK_EQ(empty.freeBeds, 2); + CHECK_EQ(empty.workstations, 2); + CHECK_EQ(empty.foodStock, 0); + CHECK(!empty.canGrow()); + + villagers[0].food = villagerBreedingFoodCost; + villagers[1].food = villagerBreedingFoodCost; + VillageCensus fed = takeVillageCensus(villagers, pois, villageCenter, 12); + CHECK_EQ(fed.willingBreeders, 2); + CHECK_EQ(fed.foodStock, villagerBreedingFoodCost * 2); + CHECK(fed.canGrow()); + + CHECK(assignVillagerBed(villagers[0], pois)); + CHECK(assignVillagerBed(villagers[1], pois)); + VillageCensus full = takeVillageCensus(villagers, pois, villageCenter, 12); + CHECK_EQ(full.freeBeds, 0); + CHECK(!full.canGrow()); + CHECK_EQ(full.capacity(), 2); +} + +VF_TEST(breedingSpendsFoodAndFillsTheFreeBeds) { + World world = makeVillage(); + placePoi(world, 6, 0, Block::Bed); + PoiRegistry pois; + pois.scan(world, villageCenter, 12, 4); + CHECK_EQ(pois.bedCount(), 3); + + std::vector villagers{makeWorker(1, 1, 1, 81u), makeWorker(2, 2, 1, 82u)}; + villagers[0].food = villagerBreedingFoodCost * 2; + villagers[1].food = villagerBreedingFoodCost * 2; + + uint32_t rng = 4242u; + int born = breedVillagers(villagers, pois, villageCenter, 12, rng); + CHECK_EQ(born, 2); + CHECK_EQ(static_cast(villagers.size()), 4); + CHECK_EQ(villagers[0].food, 0); + CHECK_EQ(villagers[1].food, 0); + CHECK_EQ(pois.freeBedCount(), 1); + CHECK_EQ(villagers[2].id, 3); + CHECK_EQ(villagers[3].id, 4); + CHECK(villagers[2].bedIndex >= 0); + CHECK(villagers[3].bedIndex >= 0); + CHECK(villagers[2].bedIndex != villagers[3].bedIndex); + + CHECK_EQ(breedVillagers(villagers, pois, villageCenter, 12, rng), 0); +} + +VF_TEST(nitwitsNeverTakeAWorkstationEvenWhenOneIsFree) { + int nitwits = 0; + int found = -1; + for (int id = 1; id <= 40; ++id) { + Villager candidate = makeVillager(id, {0.5f, static_cast(walkY), 0.5f}, 900u); + if (candidate.profession == VillagerProfession::Nitwit) { + ++nitwits; + if (found < 0) found = id; + } + } + CHECK(nitwits > 0); + CHECK(nitwits < 40); + + World world = makeVillage(); + PoiRegistry pois; + pois.scan(world, villageCenter, 12, 4); + + Villager nitwit = makeVillager(found, {-1.5f, static_cast(walkY), 0.5f}, 900u); + CHECK(nitwit.profession == VillagerProfession::Nitwit); + CHECK(!nitwit.employed()); + + TimeOfDay clock = clockAtFraction(0.35); + VillagerSchedule schedule; + runTicks(world, nitwit, pois, clock, schedule, false, 400); + CHECK(nitwit.profession == VillagerProfession::Nitwit); + CHECK_EQ(nitwit.workstationIndex, -1); + CHECK(nitwit.activity == VillagerActivity::Idle); + CHECK_EQ(pois.freeWorkstationCount(), 2); + CHECK(nitwit.bedIndex >= 0); + CHECK(!assignVillagerWorkstation(nitwit, pois)); +}