From a9dbd08dec933ff533e8b3fa81babbd5c850b043 Mon Sep 17 00:00:00 2001 From: Ivan Savenko Date: Wed, 20 Sep 2023 13:53:06 +0300 Subject: [PATCH] Compute player contacts only once on turn start --- server/processors/TurnOrderProcessor.cpp | 31 +++++++++++++++++++++--- server/processors/TurnOrderProcessor.h | 25 ++++++++++++++++++- 2 files changed, 52 insertions(+), 4 deletions(-) diff --git a/server/processors/TurnOrderProcessor.cpp b/server/processors/TurnOrderProcessor.cpp index 81790838c..08f471bfe 100644 --- a/server/processors/TurnOrderProcessor.cpp +++ b/server/processors/TurnOrderProcessor.cpp @@ -38,6 +38,26 @@ int TurnOrderProcessor::simturnsTurnsMinLimit() const return 0; } +void TurnOrderProcessor::updateContactStatus() +{ + blockedContacts.clear(); + + assert(actedPlayers.empty()); + assert(actingPlayers.empty()); + + for (auto left : awaitingPlayers) + { + for(auto right : awaitingPlayers) + { + if (left == right) + continue; + + if (computeCanActSimultaneously(left, right)) + blockedContacts.push_back({left, right}); + } + } +} + bool TurnOrderProcessor::playersInContact(PlayerColor left, PlayerColor right) const { // TODO: refactor, cleanup and optimize @@ -92,10 +112,11 @@ bool TurnOrderProcessor::playersInContact(PlayerColor left, PlayerColor right) c bool TurnOrderProcessor::isContactAllowed(PlayerColor active, PlayerColor waiting) const { - return true; + assert(active != waiting); + return !vstd::contains(blockedContacts, PlayerPair{active, waiting}); } -bool TurnOrderProcessor::canActSimultaneously(PlayerColor active, PlayerColor waiting) const +bool TurnOrderProcessor::computeCanActSimultaneously(PlayerColor active, PlayerColor waiting) const { const auto * activeInfo = gameHandler->getPlayerState(active, false); const auto * waitingInfo = gameHandler->getPlayerState(waiting, false); @@ -155,7 +176,7 @@ bool TurnOrderProcessor::canStartTurn(PlayerColor which) const for (auto player : actingPlayers) { - if (!canActSimultaneously(player, which)) + if (player != which && isContactAllowed(player, which)) return false; } @@ -180,6 +201,7 @@ void TurnOrderProcessor::doStartNewDay() std::swap(actedPlayers, awaitingPlayers); gameHandler->onNewTurn(); + updateContactStatus(); tryStartTurnsForPlayers(); } @@ -277,6 +299,9 @@ bool TurnOrderProcessor::onPlayerEndsTurn(PlayerColor which) void TurnOrderProcessor::onGameStarted() { + if (actingPlayers.empty()) + updateContactStatus(); + // this may be game load - send notification to players that they can act auto actingPlayersCopy = actingPlayers; for (auto player : actingPlayersCopy) diff --git a/server/processors/TurnOrderProcessor.h b/server/processors/TurnOrderProcessor.h index e7625307a..378ed007f 100644 --- a/server/processors/TurnOrderProcessor.h +++ b/server/processors/TurnOrderProcessor.h @@ -17,6 +17,26 @@ class TurnOrderProcessor : boost::noncopyable { CGameHandler * gameHandler; + struct PlayerPair + { + PlayerColor a; + PlayerColor b; + + bool operator == (const PlayerPair & other) const + { + return (a == other.a && b == other.b) || (a == other.b && b == other.a); + } + + template + void serialize(Handler & h, const int version) + { + h & a; + h & b; + } + }; + + std::vector blockedContacts; + std::set awaitingPlayers; std::set actingPlayers; std::set actedPlayers; @@ -31,7 +51,7 @@ class TurnOrderProcessor : boost::noncopyable bool playersInContact(PlayerColor left, PlayerColor right) const; /// Returns true if waiting player can act alongside with currently acting player - bool canActSimultaneously(PlayerColor active, PlayerColor waiting) const; + bool computeCanActSimultaneously(PlayerColor active, PlayerColor waiting) const; /// Returns true if left player must act before right player bool mustActBefore(PlayerColor left, PlayerColor right) const; @@ -42,6 +62,8 @@ class TurnOrderProcessor : boost::noncopyable /// Starts turn for all players that can start turn void tryStartTurnsForPlayers(); + void updateContactStatus(); + void doStartNewDay(); void doStartPlayerTurn(PlayerColor which); void doEndPlayerTurn(PlayerColor which); @@ -70,6 +92,7 @@ public: template void serialize(Handler & h, const int version) { + h & blockedContacts; h & awaitingPlayers; h & actingPlayers; h & actedPlayers;