2
0
Эх сурвалжийг харах

Compute player contacts only once on turn start

Ivan Savenko 2 жил өмнө
parent
commit
a9dbd08dec

+ 28 - 3
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)

+ 24 - 1
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<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;