1
0
mirror of https://github.com/vcmi/vcmi.git synced 2024-12-24 22:14:36 +02:00

Fix turn ending

This commit is contained in:
Ivan Savenko 2023-08-23 18:46:30 +03:00
parent c4bc6840ea
commit d83aa828f6
8 changed files with 43 additions and 22 deletions

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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