Generalize tax counters to 5 sequential slots with server-enforced ordering

This commit is contained in:
DawnFire42 2026-08-10 20:04:51 -04:00
parent 876a14758e
commit 4354191918
No known key found for this signature in database
GPG key ID: 24BB855EE2911B33
14 changed files with 352 additions and 251 deletions

View file

@ -18,9 +18,11 @@ namespace
{
constexpr int UserCounterId = CounterIds::FirstUserId;
Server_Counter makeCounter(int id, int count)
Server_Counter makeCounter(int id, int count, bool active = true)
{
return Server_Counter(id, "c", color(), 20, count);
Server_Counter c(id, "c", color(), 20, count);
(void)c.setActive(active);
return c;
}
} // namespace
@ -41,12 +43,12 @@ TEST(EvaluateDelCounter, RejectsWhenPlayerConceded)
TEST(EvaluateDelCounter, RejectsTaxCounters)
{
Server_Counter commander = makeCounter(CounterIds::CommanderTax, 0);
EXPECT_EQ(Server_Player::evaluateDelCounter(true, false, CounterIds::CommanderTax, &commander),
Server_Counter tax1 = makeCounter(CounterIds::TaxCounter1, 0);
EXPECT_EQ(Server_Player::evaluateDelCounter(true, false, CounterIds::TaxCounter1, &tax1),
Response::RespFunctionNotAllowed);
Server_Counter partner = makeCounter(CounterIds::PartnerTax, 0);
EXPECT_EQ(Server_Player::evaluateDelCounter(true, false, CounterIds::PartnerTax, &partner),
Server_Counter tax2 = makeCounter(CounterIds::TaxCounter2, 0);
EXPECT_EQ(Server_Player::evaluateDelCounter(true, false, CounterIds::TaxCounter2, &tax2),
Response::RespFunctionNotAllowed);
}
@ -63,125 +65,146 @@ TEST(EvaluateDelCounter, AllowsDeletingUserCounter)
TEST(EvaluateDelCounter, GameNotStartedTakesPrecedenceOverTaxGuard)
{
Server_Counter commander = makeCounter(CounterIds::CommanderTax, 0);
EXPECT_EQ(Server_Player::evaluateDelCounter(false, false, CounterIds::CommanderTax, &commander),
Server_Counter tax1 = makeCounter(CounterIds::TaxCounter1, 0);
EXPECT_EQ(Server_Player::evaluateDelCounter(false, false, CounterIds::TaxCounter1, &tax1),
Response::RespGameNotStarted);
}
TEST(EvaluateSetCounterActive, RejectsWhenGameNotStarted)
{
Server_Counter counter = makeCounter(CounterIds::CommanderTax, 0);
Server_Counter counter = makeCounter(CounterIds::TaxCounter1, 0);
EXPECT_EQ(Server_Player::evaluateSetCounterActive(/*gameStarted=*/false, /*playerConceded=*/false,
/*commandZoneEnabled=*/true, CounterIds::CommanderTax, &counter,
/*requestedActive=*/true),
/*commandZoneEnabled=*/true, CounterIds::TaxCounter1, &counter,
/*requestedActive=*/true, nullptr, nullptr),
Response::RespGameNotStarted);
}
TEST(EvaluateSetCounterActive, RejectsWhenPlayerConceded)
{
Server_Counter counter = makeCounter(CounterIds::CommanderTax, 0);
EXPECT_EQ(Server_Player::evaluateSetCounterActive(true, /*playerConceded=*/true, true, CounterIds::CommanderTax,
&counter, true),
Server_Counter counter = makeCounter(CounterIds::TaxCounter1, 0);
EXPECT_EQ(Server_Player::evaluateSetCounterActive(true, /*playerConceded=*/true, true, CounterIds::TaxCounter1,
&counter, true, nullptr, nullptr),
Response::RespContextError);
}
TEST(EvaluateSetCounterActive, RejectsNonTaxCounter)
{
Server_Counter counter = makeCounter(UserCounterId, 0);
EXPECT_EQ(Server_Player::evaluateSetCounterActive(true, false, true, UserCounterId, &counter, true),
Response::RespFunctionNotAllowed);
EXPECT_EQ(
Server_Player::evaluateSetCounterActive(true, false, true, UserCounterId, &counter, true, nullptr, nullptr),
Response::RespFunctionNotAllowed);
}
TEST(EvaluateSetCounterActive, RejectsWhenCommandZoneDisabled)
{
Server_Counter counter = makeCounter(CounterIds::CommanderTax, 0);
Server_Counter counter = makeCounter(CounterIds::TaxCounter1, 0);
EXPECT_EQ(Server_Player::evaluateSetCounterActive(true, false, /*commandZoneEnabled=*/false,
CounterIds::CommanderTax, &counter, true),
CounterIds::TaxCounter1, &counter, true, nullptr, nullptr),
Response::RespContextError);
}
TEST(EvaluateSetCounterActive, RejectsMissingCounter)
{
EXPECT_EQ(Server_Player::evaluateSetCounterActive(true, false, true, CounterIds::CommanderTax, nullptr, true),
EXPECT_EQ(Server_Player::evaluateSetCounterActive(true, false, true, CounterIds::TaxCounter1, nullptr, true,
nullptr, nullptr),
Response::RespNameNotFound);
}
TEST(EvaluateSetCounterActive, RejectsDisablingWhenTaxAccumulated)
{
Server_Counter counter = makeCounter(CounterIds::CommanderTax, 3);
EXPECT_EQ(Server_Player::evaluateSetCounterActive(true, false, true, CounterIds::CommanderTax, &counter,
/*requestedActive=*/false),
Server_Counter counter = makeCounter(CounterIds::TaxCounter1, 3);
EXPECT_EQ(Server_Player::evaluateSetCounterActive(true, false, true, CounterIds::TaxCounter1, &counter,
/*requestedActive=*/false, nullptr, nullptr),
Response::RespContextError);
}
TEST(EvaluateSetCounterActive, AllowsEnablingWithAccumulatedTax)
{
Server_Counter counter = makeCounter(CounterIds::CommanderTax, 3);
EXPECT_EQ(Server_Player::evaluateSetCounterActive(true, false, true, CounterIds::CommanderTax, &counter,
/*requestedActive=*/true),
Server_Counter counter = makeCounter(CounterIds::TaxCounter1, 3);
EXPECT_EQ(Server_Player::evaluateSetCounterActive(true, false, true, CounterIds::TaxCounter1, &counter,
/*requestedActive=*/true, nullptr, nullptr),
Response::RespOk);
}
TEST(EvaluateSetCounterActive, AllowsDisablingWhenCounterIsZero)
{
Server_Counter counter = makeCounter(CounterIds::CommanderTax, 0);
EXPECT_EQ(Server_Player::evaluateSetCounterActive(true, false, true, CounterIds::CommanderTax, &counter,
/*requestedActive=*/false),
Server_Counter counter = makeCounter(CounterIds::TaxCounter1, 0);
EXPECT_EQ(Server_Player::evaluateSetCounterActive(true, false, true, CounterIds::TaxCounter1, &counter,
/*requestedActive=*/false, nullptr, nullptr),
Response::RespOk);
}
TEST(EvaluateSetCounterActive, AllowsEnablingPartnerTax)
TEST(EvaluateSetCounterActive, AllowsEnabling2ndTaxWhen1stIsActive)
{
Server_Counter counter = makeCounter(CounterIds::PartnerTax, 0);
EXPECT_EQ(Server_Player::evaluateSetCounterActive(true, false, true, CounterIds::PartnerTax, &counter,
/*requestedActive=*/true),
Server_Counter tax1 = makeCounter(CounterIds::TaxCounter1, 0, true);
Server_Counter tax2 = makeCounter(CounterIds::TaxCounter2, 0, false);
EXPECT_EQ(Server_Player::evaluateSetCounterActive(true, false, true, CounterIds::TaxCounter2, &tax2,
/*requestedActive=*/true, &tax1, nullptr),
Response::RespOk);
}
TEST(EvaluateSetCounterActive, RejectsDisablingPartnerTaxWhenAccumulated)
TEST(EvaluateSetCounterActive, RejectsEnabling2ndTaxWhen1stIsInactive)
{
Server_Counter counter = makeCounter(CounterIds::PartnerTax, 2);
EXPECT_EQ(Server_Player::evaluateSetCounterActive(true, false, true, CounterIds::PartnerTax, &counter,
/*requestedActive=*/false),
Server_Counter tax1 = makeCounter(CounterIds::TaxCounter1, 0, false);
Server_Counter tax2 = makeCounter(CounterIds::TaxCounter2, 0, false);
EXPECT_EQ(Server_Player::evaluateSetCounterActive(true, false, true, CounterIds::TaxCounter2, &tax2,
/*requestedActive=*/true, &tax1, nullptr),
Response::RespContextError);
}
TEST(EvaluateSetCounterActive, AllowsDisabling1stTaxWhen2ndIsInactive)
{
Server_Counter tax1 = makeCounter(CounterIds::TaxCounter1, 0, true);
Server_Counter tax2 = makeCounter(CounterIds::TaxCounter2, 0, false);
EXPECT_EQ(Server_Player::evaluateSetCounterActive(true, false, true, CounterIds::TaxCounter1, &tax1,
/*requestedActive=*/false, nullptr, &tax2),
Response::RespOk);
}
TEST(EvaluateSetCounterActive, RejectsDisabling1stTaxWhen2ndIsActive)
{
Server_Counter tax1 = makeCounter(CounterIds::TaxCounter1, 0, true);
Server_Counter tax2 = makeCounter(CounterIds::TaxCounter2, 0, true);
EXPECT_EQ(Server_Player::evaluateSetCounterActive(true, false, true, CounterIds::TaxCounter1, &tax1,
/*requestedActive=*/false, nullptr, &tax2),
Response::RespContextError);
}
TEST(EvaluateCreateCounter, RejectsWhenGameNotStarted)
{
EXPECT_EQ(Server_Player::evaluateCreateCounter(/*gameStarted=*/false, /*playerConceded=*/false, "mycounter"),
EXPECT_EQ(Server_Player::evaluateCreateCounter(/*gameStarted=*/false, /*playerConceded=*/false, "test"),
Response::RespGameNotStarted);
}
TEST(EvaluateCreateCounter, RejectsWhenPlayerConceded)
{
EXPECT_EQ(Server_Player::evaluateCreateCounter(/*gameStarted=*/true, /*playerConceded=*/true, "mycounter"),
Response::RespContextError);
EXPECT_EQ(Server_Player::evaluateCreateCounter(true, /*playerConceded=*/true, "test"), Response::RespContextError);
}
TEST(EvaluateCreateCounter, RejectsCommanderTaxName)
TEST(EvaluateCreateCounter, RejectsTaxCounterNames)
{
EXPECT_EQ(Server_Player::evaluateCreateCounter(true, false, CounterNames::CommanderTax),
EXPECT_EQ(Server_Player::evaluateCreateCounter(true, false, CounterNames::TaxCounter1),
Response::RespFunctionNotAllowed);
EXPECT_EQ(Server_Player::evaluateCreateCounter(true, false, CounterNames::TaxCounter2),
Response::RespFunctionNotAllowed);
EXPECT_EQ(Server_Player::evaluateCreateCounter(true, false, CounterNames::TaxCounter3),
Response::RespFunctionNotAllowed);
EXPECT_EQ(Server_Player::evaluateCreateCounter(true, false, CounterNames::TaxCounter4),
Response::RespFunctionNotAllowed);
EXPECT_EQ(Server_Player::evaluateCreateCounter(true, false, CounterNames::TaxCounter5),
Response::RespFunctionNotAllowed);
}
TEST(EvaluateCreateCounter, RejectsPartnerTaxName)
TEST(EvaluateCreateCounter, AllowsUserCounterName)
{
EXPECT_EQ(Server_Player::evaluateCreateCounter(true, false, CounterNames::PartnerTax),
Response::RespFunctionNotAllowed);
}
TEST(EvaluateCreateCounter, AllowsOrdinaryNames)
{
EXPECT_EQ(Server_Player::evaluateCreateCounter(true, false, "life"), Response::RespOk);
EXPECT_EQ(Server_Player::evaluateCreateCounter(true, false, "poison"), Response::RespOk);
EXPECT_EQ(Server_Player::evaluateCreateCounter(true, false, ""), Response::RespOk);
}
TEST(EvaluateModifyCounter, RejectsWhenGameNotStarted)
{
Server_Counter counter = makeCounter(UserCounterId, 0);
EXPECT_EQ(Server_Player::evaluateModifyCounter(/*gameStarted=*/false, false, /*commandZoneEnabled=*/true,
UserCounterId, &counter),
EXPECT_EQ(Server_Player::evaluateModifyCounter(/*gameStarted=*/false, /*playerConceded=*/false, true, UserCounterId,
&counter),
Response::RespGameNotStarted);
}
@ -192,48 +215,46 @@ TEST(EvaluateModifyCounter, RejectsWhenPlayerConceded)
Response::RespContextError);
}
TEST(EvaluateModifyCounter, AllowsUserCounter)
{
Server_Counter counter = makeCounter(UserCounterId, 0);
EXPECT_EQ(Server_Player::evaluateModifyCounter(true, false, /*commandZoneEnabled=*/false, UserCounterId, &counter),
Response::RespOk);
}
TEST(EvaluateModifyCounter, RejectsMissingCounter)
{
EXPECT_EQ(Server_Player::evaluateModifyCounter(true, false, true, UserCounterId, nullptr),
Response::RespNameNotFound);
}
TEST(EvaluateModifyCounter, AllowsUserCounter)
{
Server_Counter counter = makeCounter(UserCounterId, 5);
EXPECT_EQ(Server_Player::evaluateModifyCounter(true, false, true, UserCounterId, &counter), Response::RespOk);
}
TEST(EvaluateModifyCounter, RejectsTaxCounterWhenCommandZoneDisabled)
{
Server_Counter counter = makeCounter(CounterIds::CommanderTax, 0);
EXPECT_EQ(Server_Player::evaluateModifyCounter(true, false, /*commandZoneEnabled=*/false, CounterIds::CommanderTax,
Server_Counter counter = makeCounter(CounterIds::TaxCounter1, 0);
EXPECT_EQ(Server_Player::evaluateModifyCounter(true, false, /*commandZoneEnabled=*/false, CounterIds::TaxCounter1,
&counter),
Response::RespContextError);
}
TEST(EvaluateModifyCounter, RejectsInactiveTaxCounter)
{
Server_Counter counter = makeCounter(CounterIds::PartnerTax, 0);
(void)counter.setActive(false);
EXPECT_EQ(Server_Player::evaluateModifyCounter(true, false, /*commandZoneEnabled=*/true, CounterIds::PartnerTax,
Server_Counter counter = makeCounter(CounterIds::TaxCounter2, 0, false);
EXPECT_EQ(Server_Player::evaluateModifyCounter(true, false, /*commandZoneEnabled=*/true, CounterIds::TaxCounter2,
&counter),
Response::RespContextError);
}
TEST(EvaluateModifyCounter, AllowsActiveTaxCounter)
{
Server_Counter counter = makeCounter(CounterIds::CommanderTax, 0);
EXPECT_EQ(Server_Player::evaluateModifyCounter(true, false, /*commandZoneEnabled=*/true, CounterIds::CommanderTax,
Server_Counter counter = makeCounter(CounterIds::TaxCounter1, 0, true);
EXPECT_EQ(Server_Player::evaluateModifyCounter(true, false, /*commandZoneEnabled=*/true, CounterIds::TaxCounter1,
&counter),
Response::RespOk);
}
TEST(EvaluateModifyCounter, RejectsMissingTaxCounter)
{
EXPECT_EQ(Server_Player::evaluateModifyCounter(true, false, /*commandZoneEnabled=*/true, CounterIds::CommanderTax,
/*counter=*/nullptr),
EXPECT_EQ(Server_Player::evaluateModifyCounter(true, false, /*commandZoneEnabled=*/true, CounterIds::TaxCounter1,
nullptr),
Response::RespNameNotFound);
}

View file

@ -52,25 +52,25 @@ TEST(NewCounterId, SkipsReservedRangeWhenOnlyReservedCountersExist)
TEST(NewCounterId, SkipsTaxCounterIds)
{
PlayerFixture f;
f.player.addCounter(new Server_Counter(CounterIds::CommanderTax, "tax1", color(), 0, 0));
f.player.addCounter(new Server_Counter(CounterIds::PartnerTax, "tax2", color(), 0, 0));
f.player.addCounter(new Server_Counter(CounterIds::TaxCounter1, "tax1", color(), 0, 0));
f.player.addCounter(new Server_Counter(CounterIds::TaxCounter2, "tax2", color(), 0, 0));
EXPECT_EQ(f.player.newCounterId(), CounterIds::FirstUserId);
}
TEST(NewCounterId, ReturnsNextIdAboveHighestUserCounter)
{
PlayerFixture f;
f.player.addCounter(new Server_Counter(CounterIds::FirstUserId, "a", color(), 20, 0)); // 10
f.player.addCounter(new Server_Counter(15, "b", color(), 20, 0));
EXPECT_EQ(f.player.newCounterId(), 16);
f.player.addCounter(new Server_Counter(CounterIds::FirstUserId, "a", color(), 20, 0));
f.player.addCounter(new Server_Counter(CounterIds::FirstUserId + 2, "b", color(), 20, 0));
EXPECT_EQ(f.player.newCounterId(), CounterIds::FirstUserId + 3);
}
TEST(NewCounterId, IgnoresReservedCountersWhenUserCountersPresent)
{
PlayerFixture f;
f.player.addCounter(new Server_Counter(5, "r", color(), 20, 0)); // reserved range
f.player.addCounter(new Server_Counter(11, "user", color(), 20, 0)); // user range
EXPECT_EQ(f.player.newCounterId(), 12);
f.player.addCounter(new Server_Counter(5, "r", color(), 20, 0)); // reserved range
f.player.addCounter(new Server_Counter(CounterIds::FirstUserId, "user", color(), 20, 0)); // user range
EXPECT_EQ(f.player.newCounterId(), CounterIds::FirstUserId + 1);
}
int main(int argc, char **argv)

View file

@ -86,34 +86,40 @@ struct SetupFixture
};
} // namespace
TEST(SetupZonesCommandZone, CreatesTaxCountersWhenEnabled)
TEST(SetupZonesCommandZone, CreatesAllTaxCountersWhenEnabled)
{
SetupFixture f(true);
const QMap<int, Server_Counter *> &counters = f.player.getCounters();
EXPECT_TRUE(f.player.getZones().contains(ZoneNames::COMMAND));
ASSERT_TRUE(counters.contains(CounterIds::CommanderTax));
ASSERT_TRUE(counters.contains(CounterIds::PartnerTax));
const Server_Counter *commander = counters.value(CounterIds::CommanderTax);
const Server_Counter *partner = counters.value(CounterIds::PartnerTax);
for (int i = 0; i < CounterIds::TaxCounterCount; ++i) {
int id = CounterIds::taxCounterIdFromIndex(i);
ASSERT_TRUE(counters.contains(id));
}
EXPECT_TRUE(commander->isActive());
EXPECT_FALSE(partner->isActive());
EXPECT_EQ(commander->getCount(), 0);
EXPECT_EQ(partner->getCount(), 0);
const Server_Counter *tax1 = counters.value(CounterIds::TaxCounter1);
EXPECT_TRUE(tax1->isActive());
EXPECT_EQ(tax1->getCount(), 0);
for (int i = 1; i < CounterIds::TaxCounterCount; ++i) {
int id = CounterIds::taxCounterIdFromIndex(i);
const Server_Counter *counter = counters.value(id);
EXPECT_FALSE(counter->isActive());
EXPECT_EQ(counter->getCount(), 0);
}
}
TEST(SetupZonesCommandZone, TaxCountersUseCommanderBounds)
TEST(SetupZonesCommandZone, TaxCountersUseBounds)
{
SetupFixture f(true);
Server_Counter *commander = f.player.getCounters().value(CounterIds::CommanderTax);
ASSERT_NE(commander, nullptr);
Server_Counter *tax1 = f.player.getCounters().value(CounterIds::TaxCounter1);
ASSERT_NE(tax1, nullptr);
EXPECT_TRUE(commander->setCount(MAX_COUNTER_VALUE + 1000));
EXPECT_EQ(commander->getCount(), MAX_COUNTER_VALUE);
EXPECT_TRUE(commander->setCount(-1));
EXPECT_EQ(commander->getCount(), 0);
EXPECT_TRUE(tax1->setCount(MAX_COUNTER_VALUE + 1000));
EXPECT_EQ(tax1->getCount(), MAX_COUNTER_VALUE);
EXPECT_TRUE(tax1->setCount(-1));
EXPECT_EQ(tax1->getCount(), 0);
}
TEST(SetupZonesCommandZone, NoTaxCountersWhenDisabled)
@ -122,8 +128,12 @@ TEST(SetupZonesCommandZone, NoTaxCountersWhenDisabled)
const QMap<int, Server_Counter *> &counters = f.player.getCounters();
EXPECT_FALSE(f.player.getZones().contains(ZoneNames::COMMAND));
EXPECT_FALSE(counters.contains(CounterIds::CommanderTax));
EXPECT_FALSE(counters.contains(CounterIds::PartnerTax));
for (int i = 0; i < CounterIds::TaxCounterCount; ++i) {
int id = CounterIds::taxCounterIdFromIndex(i);
EXPECT_FALSE(counters.contains(id));
}
EXPECT_TRUE(counters.contains(0));
}