Always look at top card (#4238)

* Add option to always look at top card of deck

Similar to "always reveal", but reveals card only to the owner,
not all players.

* Add option to always look at top card of deck

Similar to "always reveal", but reveals card only to the owner,
not all players.

* Update bug_report.md (#4246)

* Update bug_report.md

* reproduction steps

* Update to address review comments

* Clangify

* set playerId on dumpEvent

Co-authored-by: tooomm <tooomm@users.noreply.github.com>
Co-authored-by: ebbit1q <ebbit1q@gmail.com>
Co-authored-by: Zach H <zahalpern+github@gmail.com>
This commit is contained in:
omegaula 2021-03-13 14:54:13 -05:00 committed by GitHub
parent 00ed5c370c
commit 073349fd05
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
12 changed files with 120 additions and 54 deletions

View file

@ -7,5 +7,8 @@ message Command_ChangeZoneProperties {
}
optional string zone_name = 1;
// Reveal top card to all players.
optional bool always_reveal_top_card = 10;
// reveal top card to the owner.
optional bool always_look_at_top_card = 11;
}

View file

@ -7,5 +7,8 @@ message Event_ChangeZoneProperties {
}
optional string zone_name = 1;
// Reveal top card to all players.
optional bool always_reveal_top_card = 10;
// reveal top card to the owner.
optional bool always_look_at_top_card = 11;
}

View file

@ -21,5 +21,8 @@ message ServerInfo_Zone {
optional bool with_coords = 3;
optional sint32 card_count = 4;
repeated ServerInfo_Card card_list = 5;
// Reveal top card to all players.
optional bool always_reveal_top_card = 10;
// reveal top card to the owner.
optional bool always_look_at_top_card = 11;
}

View file

@ -32,7 +32,7 @@ Server_CardZone::Server_CardZone(Server_Player *_player,
bool _has_coords,
ServerInfo_Zone::ZoneType _type)
: player(_player), name(_name), has_coords(_has_coords), type(_type), cardsBeingLookedAt(0),
alwaysRevealTopCard(false)
alwaysRevealTopCard(false), alwaysLookAtTopCard(false)
{
}
@ -305,6 +305,7 @@ void Server_CardZone::getInfo(ServerInfo_Zone *info, Server_Player *playerWhosAs
info->set_with_coords(has_coords);
info->set_card_count(cards.size());
info->set_always_reveal_top_card(alwaysRevealTopCard);
info->set_always_look_at_top_card(alwaysLookAtTopCard);
if ((((playerWhosAsking == player) || omniscient) && (type != ServerInfo_Zone::HiddenZone)) ||
((playerWhosAsking != player) && (type == ServerInfo_Zone::PublicZone))) {
QListIterator<Server_Card *> cardIterator(cards);

View file

@ -42,6 +42,7 @@ private:
int cardsBeingLookedAt;
QSet<int> playersWithWritePermission;
bool alwaysRevealTopCard;
bool alwaysLookAtTopCard;
QList<Server_Card *> cards;
QMap<int, QMap<int, Server_Card *>> coordinateMap; // y -> (x -> card)
QMap<int, QMultiMap<QString, int>> freePilesMap; // y -> (cardName -> x)
@ -108,6 +109,14 @@ public:
{
alwaysRevealTopCard = _alwaysRevealTopCard;
}
bool getAlwaysLookAtTopCard() const
{
return alwaysLookAtTopCard;
}
void setAlwaysLookAtTopCard(bool _alwaysLookAtTopCard)
{
alwaysLookAtTopCard = _alwaysLookAtTopCard;
}
};
#endif

View file

@ -318,18 +318,41 @@ Response::ResponseCode Server_Player::drawCards(GameEventStorage &ges, int numbe
ges.enqueueGameEvent(eventPrivate, playerId, GameEventStorageItem::SendToPrivate, playerId);
ges.enqueueGameEvent(eventOthers, playerId, GameEventStorageItem::SendToOthers);
if (deckZone->getAlwaysRevealTopCard() && !deckZone->getCards().isEmpty()) {
Event_RevealCards revealEvent;
revealEvent.set_zone_name(deckZone->getName().toStdString());
revealEvent.set_card_id(0);
deckZone->getCards().first()->getInfo(revealEvent.add_cards());
ges.enqueueGameEvent(revealEvent, playerId);
}
revealTopCardIfNeeded(deckZone, ges);
return Response::RespOk;
}
void Server_Player::revealTopCardIfNeeded(Server_CardZone *zone, GameEventStorage &ges)
{
if (zone->getCards().isEmpty()) {
return;
}
if (zone->getAlwaysRevealTopCard()) {
Event_RevealCards revealEvent;
revealEvent.set_zone_name(zone->getName().toStdString());
revealEvent.set_card_id(0);
zone->getCards().first()->getInfo(revealEvent.add_cards());
ges.enqueueGameEvent(revealEvent, playerId);
return;
}
if (zone->getAlwaysLookAtTopCard()) {
Event_DumpZone dumpEvent;
dumpEvent.set_zone_owner_id(playerId);
dumpEvent.set_zone_name(zone->getName().toStdString());
dumpEvent.set_number_cards(1);
ges.enqueueGameEvent(dumpEvent, playerId, GameEventStorageItem::SendToOthers);
Event_RevealCards revealEvent;
revealEvent.set_zone_name(zone->getName().toStdString());
revealEvent.set_number_of_cards(1);
revealEvent.set_card_id(0);
zone->getCards().first()->getInfo(revealEvent.add_cards());
ges.enqueueGameEvent(revealEvent, playerId, GameEventStorageItem::SendToPrivate, playerId);
}
}
class Server_Player::MoveCardCompareFunctor
{
private:
@ -594,21 +617,11 @@ Response::ResponseCode Server_Player::moveCard(GameEventStorage &ges,
setCardAttrHelper(ges, targetzone->getPlayer()->getPlayerId(), targetzone->getName(), card->getId(),
AttrPT, ptString);
}
if (startzone->getAlwaysRevealTopCard() && !startzone->getCards().isEmpty() && (originalPosition == 0)) {
Event_RevealCards revealEvent;
revealEvent.set_zone_name(startzone->getName().toStdString());
revealEvent.set_card_id(0);
startzone->getCards().first()->getInfo(revealEvent.add_cards());
ges.enqueueGameEvent(revealEvent, playerId);
if (originalPosition == 0) {
revealTopCardIfNeeded(startzone, ges);
}
if (targetzone->getAlwaysRevealTopCard() && !targetzone->getCards().isEmpty() && (newX == 0)) {
Event_RevealCards revealEvent;
revealEvent.set_zone_name(targetzone->getName().toStdString());
revealEvent.set_card_id(0);
targetzone->getCards().first()->getInfo(revealEvent.add_cards());
ges.enqueueGameEvent(revealEvent, playerId);
if (newX == 0) {
revealTopCardIfNeeded(targetzone, ges);
}
}
}
@ -977,15 +990,7 @@ Server_Player::cmdShuffle(const Command_Shuffle &cmd, ResponseContainer & /*rc*/
event.set_start(cmd.start());
event.set_end(cmd.end());
ges.enqueueGameEvent(event, playerId);
if (zone->getAlwaysRevealTopCard() && !zone->getCards().isEmpty()) {
Event_RevealCards revealEvent;
revealEvent.set_zone_name(zone->getName().toStdString());
revealEvent.set_card_id(0);
zone->getCards().first()->getInfo(revealEvent.add_cards());
ges.enqueueGameEvent(revealEvent, playerId);
}
revealTopCardIfNeeded(zone, ges);
return Response::RespOk;
}
@ -1980,27 +1985,31 @@ Response::ResponseCode Server_Player::cmdChangeZoneProperties(const Command_Chan
Event_ChangeZoneProperties event;
event.set_zone_name(cmd.zone_name());
if (cmd.has_always_reveal_top_card()) {
if (zone->getAlwaysRevealTopCard() == cmd.always_reveal_top_card()) {
return Response::RespContextError;
}
zone->setAlwaysRevealTopCard(cmd.always_reveal_top_card());
event.set_always_reveal_top_card(cmd.always_reveal_top_card());
ges.enqueueGameEvent(event, playerId);
if (!zone->getCards().isEmpty() && cmd.always_reveal_top_card()) {
Event_RevealCards revealEvent;
revealEvent.set_zone_name(zone->getName().toStdString());
revealEvent.set_card_id(0);
zone->getCards().first()->getInfo(revealEvent.add_cards());
ges.enqueueGameEvent(revealEvent, playerId);
}
return Response::RespOk;
} else {
// Neither value set -> error.
if (!cmd.has_always_look_at_top_card() && !cmd.has_always_reveal_top_card()) {
return Response::RespContextError;
}
// Neither value changed -> error.
bool alwaysRevealChanged =
cmd.has_always_reveal_top_card() && zone->getAlwaysRevealTopCard() != cmd.always_reveal_top_card();
bool alwaysLookAtTopChanged =
cmd.has_always_look_at_top_card() && zone->getAlwaysLookAtTopCard() != cmd.always_look_at_top_card();
if (!alwaysRevealChanged && !alwaysLookAtTopChanged) {
return Response::RespContextError;
}
if (cmd.has_always_reveal_top_card()) {
zone->setAlwaysRevealTopCard(cmd.always_reveal_top_card());
event.set_always_reveal_top_card(cmd.always_reveal_top_card());
}
if (cmd.has_always_look_at_top_card()) {
zone->setAlwaysLookAtTopCard(cmd.always_look_at_top_card());
event.set_always_look_at_top_card(cmd.always_look_at_top_card());
}
ges.enqueueGameEvent(event, playerId);
revealTopCardIfNeeded(zone, ges);
return Response::RespOk;
}
Response::ResponseCode

View file

@ -84,6 +84,7 @@ private:
bool readyStart;
bool conceded;
bool sideboardLocked;
void revealTopCardIfNeeded(Server_CardZone *zone, GameEventStorage &ges);
public:
mutable QMutex playerMutex;