Add distinct random hand reveals with private recipient delivery

This commit is contained in:
Bryce! 2026-11-01 21:59:21 -05:00
parent e08402ac94
commit ccdee18db2
14 changed files with 418 additions and 8 deletions

View file

@ -399,7 +399,8 @@ Response::ResponseCode Server_AbstractParticipant::cmdDumpZone(const Command_Dum
Response::ResponseCode Server_AbstractParticipant::cmdRevealCards(const Command_RevealCards & /*cmd*/,
ResponseContainer & /*rc*/,
GameEventStorage & /*ges*/)
GameEventStorage & /*ges*/,
int /*randomCount*/)
{
return Response::RespFunctionNotAllowed;
}
@ -516,6 +517,20 @@ Server_AbstractParticipant::processGameCommand(const GameCommand &command, Respo
case GameCommand::REVEAL_CARDS:
return cmdRevealCards(command.GetExtension(Command_RevealCards::ext), rc, ges);
break;
case GameCommand::REVEAL_RANDOM_CARDS: {
const auto &random = command.GetExtension(Command_RevealRandomCards::ext);
if (random.number_of_cards() <= 0) {
return Response::RespInvalidData;
}
// Reuse the existing player/judge authorization and private reveal delivery.
Command_RevealCards reveal;
reveal.set_zone_name(random.zone_name());
reveal.add_card_id(-2);
if (random.has_player_id()) {
reveal.set_player_id(random.player_id());
}
return cmdRevealCards(reveal, rc, ges, random.number_of_cards());
}
case GameCommand::MOVE_CARD:
return cmdMoveCard(command.GetExtension(Command_MoveCard::ext), rc, ges);
break;

View file

@ -169,7 +169,7 @@ public:
virtual Response::ResponseCode
cmdDumpZone(const Command_DumpZone &cmd, ResponseContainer &rc, GameEventStorage &ges);
virtual Response::ResponseCode
cmdRevealCards(const Command_RevealCards &cmd, ResponseContainer &rc, GameEventStorage &ges);
cmdRevealCards(const Command_RevealCards &cmd, ResponseContainer &rc, GameEventStorage &ges, int randomCount = 1);
virtual Response::ResponseCode
cmdReverseTurn(const Command_ReverseTurn & /*cmd*/, ResponseContainer & /*rc*/, GameEventStorage &ges);
virtual Response::ResponseCode

View file

@ -1495,8 +1495,10 @@ Server_AbstractPlayer::cmdDumpZone(const Command_DumpZone &cmd, ResponseContaine
return Response::RespOk;
}
Response::ResponseCode
Server_AbstractPlayer::cmdRevealCards(const Command_RevealCards &cmd, ResponseContainer & /*rc*/, GameEventStorage &ges)
Response::ResponseCode Server_AbstractPlayer::cmdRevealCards(const Command_RevealCards &cmd,
ResponseContainer & /*rc*/,
GameEventStorage &ges,
int randomCount)
{
if (!game->getGameStarted()) {
return Response::RespGameNotStarted;
@ -1533,11 +1535,18 @@ Server_AbstractPlayer::cmdRevealCards(const Command_RevealCards &cmd, ResponseCo
//
// This is to be compatible with clients supporting a single card_id
// value, which send value -2 to request a random card.
if (zone->getCards().isEmpty()) {
if (randomCount <= 0 || randomCount > zone->getCards().size()) {
return Response::RespContextError;
}
cardsToReveal.append(zone->getCards().at(rng->rand(0, zone->getCards().size() - 1)));
// Partial Fisher-Yates on a copy: each physical card can appear only once,
// and the hand's order and contents stay unchanged. Legacy requests use one.
auto candidates = zone->getCards();
for (int i = 0; i < randomCount; ++i) {
const int selected = rng->rand(i, candidates.size() - 1);
candidates.swapItemsAt(i, selected);
cardsToReveal.append(candidates.at(i));
}
} else {
for (auto cardId : cmd.card_id()) {
Server_Card *card = zone->getCard(cardId);

View file

@ -161,8 +161,10 @@ public:
cmdIncCardCounter(const Command_IncCardCounter &cmd, ResponseContainer &rc, GameEventStorage &ges) override;
virtual Response::ResponseCode
cmdDumpZone(const Command_DumpZone &cmd, ResponseContainer &rc, GameEventStorage &ges) override;
virtual Response::ResponseCode
cmdRevealCards(const Command_RevealCards &cmd, ResponseContainer &rc, GameEventStorage &ges) override;
virtual Response::ResponseCode cmdRevealCards(const Command_RevealCards &cmd,
ResponseContainer &rc,
GameEventStorage &ges,
int randomCount = 1) override;
virtual Response::ResponseCode cmdChangeZoneProperties(const Command_ChangeZoneProperties &cmd,
ResponseContainer &rc,
GameEventStorage &ges) override;