1
0
mirror of https://github.com/vcmi/vcmi.git synced 2024-11-24 08:32:34 +02:00

Compute player contacts only once on turn start

This commit is contained in:
Ivan Savenko 2023-09-20 13:53:06 +03:00
parent 623fb2a63e
commit a9dbd08dec
2 changed files with 52 additions and 4 deletions

View File

@ -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)

View File

@ -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<typename Handler>
void serialize(Handler & h, const int version)
{
h & a;
h & b;
}
};
std::vector<PlayerPair> blockedContacts;
std::set<PlayerColor> awaitingPlayers;
std::set<PlayerColor> actingPlayers;
std::set<PlayerColor> 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<typename Handler>
void serialize(Handler & h, const int version)
{
h & blockedContacts;
h & awaitingPlayers;
h & actingPlayers;
h & actedPlayers;