Ver Fonte

Fix turn ending

Ivan Savenko há 2 anos atrás
pai
commit
d83aa828f6

+ 2 - 1
AI/Nullkiller/Analyzers/ArmyManager.cpp

@@ -225,7 +225,8 @@ std::vector<SlotInfo> ArmyManager::getBestArmy(const IBonusBearer * armyCarrier,
 
 		if(weakest->count == 1) 
 		{
-			assert(resultingArmy.size() > 1);
+			if (resultingArmy.size() == 1)
+				logAi->warn("Unexpected resulting army size!");
 
 			resultingArmy.erase(weakest);
 		}

+ 1 - 1
include/vcmi/events/PlayerGotTurn.h

@@ -29,7 +29,7 @@ public:
 	using ExecHandler = Sub::ExecHandler;
 
 	static Sub * getRegistry();
-	static void defaultExecute(const EventBus * bus, PlayerColor & player);
+	static void defaultExecute(const EventBus * bus, const PlayerColor & player);
 
 	virtual PlayerColor getPlayer() const = 0;
 	virtual void setPlayer(const PlayerColor & value) = 0;

+ 1 - 2
lib/events/PlayerGotTurn.cpp

@@ -24,12 +24,11 @@ SubscriptionRegistry<PlayerGotTurn> * PlayerGotTurn::getRegistry()
 	return Instance.get();
 }
 
-void PlayerGotTurn::defaultExecute(const EventBus * bus, PlayerColor & player)
+void PlayerGotTurn::defaultExecute(const EventBus * bus, const PlayerColor & player)
 {
 	CPlayerGotTurn event;
 	event.setPlayer(player);
 	bus->executeEvent(event);
-	player = event.getPlayer();
 }
 
 CPlayerGotTurn::CPlayerGotTurn() = default;

+ 3 - 2
server/CGameHandler.cpp

@@ -609,7 +609,8 @@ void CGameHandler::onPlayerTurnStarted(PlayerColor which)
 
 void CGameHandler::onPlayerTurnEnded(PlayerColor which)
 {
-
+	// 7 days without castle
+	checkVictoryLossConditionsForPlayer(which);
 }
 
 void CGameHandler::onNewTurn()
@@ -3550,7 +3551,7 @@ void CGameHandler::checkVictoryLossConditionsForPlayer(PlayerColor player)
 		// If we are called before the actual game start, there might be no current player
 		// If player making turn has lost his turn must be over as well
 		if (playerInfo && playerInfo->status != EPlayerStatus::INGAME)
-			turnOrder->onPlayerEndsTurn(gs->currentPlayer);
+			turnOrder->onPlayerEndsTurn(gs->currentPlayer, PlayerTurnEndReason::GAME_END);
 	}
 }
 

+ 1 - 1
server/NetPacksServer.cpp

@@ -40,7 +40,7 @@ void ApplyGhNetPackVisitor::visitEndTurn(EndTurn & pack)
 	if (!gh.hasPlayerAt(pack.player, pack.c))
 		gh.throwAndComplain(&pack, "No such pack.player!");
 
-	result = gh.turnOrder->onPlayerEndsTurn(pack.player);
+	result = gh.turnOrder->onPlayerEndsTurn(pack.player, PlayerTurnEndReason::CLIENT_REQUEST);
 }
 
 void ApplyGhNetPackVisitor::visitDismissHero(DismissHero & pack)

+ 1 - 1
server/TurnTimerHandler.cpp

@@ -85,7 +85,7 @@ void TurnTimerHandler::onPlayerMakingTurn(PlayerState & state, int waitTime)
 			onPlayerMakingTurn(state, waitTime);
 		}
 		else if(!gameHandler.queries->topQuery(state.color))
-			gameHandler.turnOrder->onPlayerEndsTurn(state.color);
+			gameHandler.turnOrder->onPlayerEndsTurn(state.color, PlayerTurnEndReason::TURN_TIMEOUT);
 	}
 }
 

+ 25 - 12
server/processors/TurnOrderProcessor.cpp

@@ -54,7 +54,7 @@ bool TurnOrderProcessor::canStartTurn(PlayerColor which) const
 {
 	for (auto player : awaitingPlayers)
 	{
-		if (mustActBefore(player, which))
+		if (player != which && mustActBefore(player, which))
 			return false;
 	}
 
@@ -83,18 +83,19 @@ void TurnOrderProcessor::doStartNewDay()
 		gameHandler->gameLobby()->setState(EServerState::GAMEPLAY_ENDED);
 
 	std::swap(actedPlayers, awaitingPlayers);
+
+	gameHandler->onNewTurn();
+	tryStartTurnsForPlayers();
 }
 
 void TurnOrderProcessor::doStartPlayerTurn(PlayerColor which)
 {
-	//if player runs out of time, he shouldn't get the turn (especially AI)
-	//pre-trigger may change anything, should check before each player
-	//TODO: is it enough to check only one player?
-	gameHandler->checkVictoryLossConditionsForAll();
-
 	assert(gameHandler->getPlayerState(which));
 	assert(gameHandler->getPlayerState(which)->status == EPlayerStatus::INGAME);
 
+	//Note: on game load, "actingPlayer" might already contain list of players
+	actingPlayers.insert(which);
+	awaitingPlayers.erase(which);
 	gameHandler->onPlayerTurnStarted(which);
 
 	YourTurn yt;
@@ -102,20 +103,28 @@ void TurnOrderProcessor::doStartPlayerTurn(PlayerColor which)
 	//Change local daysWithoutCastle counter for local interface message //TODO: needed?
 	yt.daysWithoutCastle = gameHandler->getPlayerState(which)->daysWithoutCastle;
 	gameHandler->sendAndApply(&yt);
+
+	assert(actingPlayers.size() == 1); // No simturns yet :(
+	assert(gameHandler->getCurrentPlayer() == *actingPlayers.begin());
 }
 
-void TurnOrderProcessor::doEndPlayerTurn(PlayerColor which)
+void TurnOrderProcessor::doEndPlayerTurn(PlayerColor which, PlayerTurnEndReason reason)
 {
 	assert(playerMakingTurn(which));
 
 	actingPlayers.erase(which);
-	actedPlayers.insert(which);
+	if (reason != PlayerTurnEndReason::GAME_END)
+		actedPlayers.insert(which);
 
 	if (!awaitingPlayers.empty())
 		tryStartTurnsForPlayers();
 
 	if (actingPlayers.empty())
 		doStartNewDay();
+
+	assert(!actingPlayers.empty());
+	assert(actingPlayers.size() == 1); // No simturns yet :(
+	assert(gameHandler->getCurrentPlayer() == *actingPlayers.begin());
 }
 
 void TurnOrderProcessor::addPlayer(PlayerColor which)
@@ -123,7 +132,7 @@ void TurnOrderProcessor::addPlayer(PlayerColor which)
 	awaitingPlayers.insert(which);
 }
 
-bool TurnOrderProcessor::onPlayerEndsTurn(PlayerColor which)
+bool TurnOrderProcessor::onPlayerEndsTurn(PlayerColor which, PlayerTurnEndReason reason)
 {
 	if (!playerMakingTurn(which))
 	{
@@ -143,18 +152,22 @@ bool TurnOrderProcessor::onPlayerEndsTurn(PlayerColor which)
 		return false;
 	}
 
-	doEndPlayerTurn(which);
+	if (reason != PlayerTurnEndReason::GAME_END)
+		gameHandler->onPlayerTurnEnded(which);
+
+	doEndPlayerTurn(which, reason);
+
 	return true;
 }
 
 void TurnOrderProcessor::onGameStarted()
 {
-	tryStartTurnsForPlayers();
-
 	// this may be game load - send notification to players that they can act
 	auto actingPlayersCopy = actingPlayers;
 	for (auto player : actingPlayersCopy)
 		doStartPlayerTurn(player);
+
+	tryStartTurnsForPlayers();
 }
 
 void TurnOrderProcessor::tryStartTurnsForPlayers()

+ 9 - 2
server/processors/TurnOrderProcessor.h

@@ -13,6 +13,13 @@
 
 class CGameHandler;
 
+enum class PlayerTurnEndReason
+{
+	CLIENT_REQUEST, // client requested end of turn (e.g. press End Turn button)
+	TURN_TIMEOUT, // Player's turn timer has run out
+	GAME_END // Player have won or lost the game
+};
+
 class TurnOrderProcessor : boost::noncopyable
 {
 	CGameHandler * gameHandler;
@@ -35,7 +42,7 @@ class TurnOrderProcessor : boost::noncopyable
 
 	void doStartNewDay();
 	void doStartPlayerTurn(PlayerColor which);
-	void doEndPlayerTurn(PlayerColor which);
+	void doEndPlayerTurn(PlayerColor which, PlayerTurnEndReason reason);
 
 public:
 	TurnOrderProcessor(CGameHandler * owner);
@@ -44,7 +51,7 @@ public:
 	void addPlayer(PlayerColor which);
 
 	/// NetPack call-in
-	bool onPlayerEndsTurn(PlayerColor which);
+	bool onPlayerEndsTurn(PlayerColor which, PlayerTurnEndReason reason);
 
 	/// Start game (or resume from save) and send YourTurn pack to player(s)
 	void onGameStarted();