Fix handling of "7 days without town" loss condition

This commit is contained in:
Ivan Savenko
2023-08-24 23:34:33 +03:00
parent 66f555f1f7
commit f9410145d6
9 changed files with 70 additions and 39 deletions
-1
View File
@@ -471,7 +471,6 @@ void ClientCommandManager::giveTurn(const PlayerColor &colorIdentifier)
{
YourTurn yt;
yt.player = colorIdentifier;
yt.daysWithoutCastle = CSH->client->getPlayerState(colorIdentifier)->daysWithoutCastle;
ApplyClientNetPackVisitor visitor(*CSH->client, *CSH->client->gameState());
yt.visit(visitor);
+1
View File
@@ -27,6 +27,7 @@ public:
virtual void visitPlayerBlocked(PlayerBlocked & pack) {}
virtual void visitPlayerCheated(PlayerCheated & pack) {}
virtual void visitYourTurn(YourTurn & pack) {}
virtual void visitYourTurn(DaysWithoutTown & pack) {}
virtual void visitTurnTimeUpdate(TurnTimeUpdate & pack) {}
virtual void visitEntitiesChanged(EntitiesChanged & pack) {}
virtual void visitSetResources(SetResources & pack) {}
+15 -1
View File
@@ -167,7 +167,21 @@ struct DLL_LINKAGE YourTurn : public CPackForClient
void applyGs(CGameState * gs) const;
PlayerColor player;
std::optional<ui8> daysWithoutCastle;
virtual void visitTyped(ICPackVisitor & visitor) override;
template <typename Handler> void serialize(Handler & h, const int version)
{
h & player;
}
};
struct DLL_LINKAGE DaysWithoutTown : public CPackForClient
{
void applyGs(CGameState * gs) const;
PlayerColor player;
std::optional<int32_t> daysWithoutCastle;
virtual void visitTyped(ICPackVisitor & visitor) override;
+18 -22
View File
@@ -108,6 +108,11 @@ void YourTurn::visitTyped(ICPackVisitor & visitor)
visitor.visitYourTurn(*this);
}
void DaysWithoutTown::visitTyped(ICPackVisitor & visitor)
{
visitor.visitYourTurn(*this);
}
void EntitiesChanged::visitTyped(ICPackVisitor & visitor)
{
visitor.visitEntitiesChanged(*this);
@@ -2025,26 +2030,6 @@ void NewTurn::applyGs(CGameState *gs)
if(gs->getDate(Date::DAY_OF_WEEK) == 1)
gs->updateRumor();
//count days without town for all players, regardless of their turn order
for (auto &p : gs->players)
{
PlayerState & playerState = p.second;
if (playerState.status == EPlayerStatus::INGAME)
{
if (playerState.towns.empty())
{
if (playerState.daysWithoutCastle)
++(*playerState.daysWithoutCastle);
else
playerState.daysWithoutCastle = std::make_optional(0);
}
else
{
playerState.daysWithoutCastle = std::nullopt;
}
}
}
}
void SetObjectProperty::applyGs(CGameState * gs) const
@@ -2063,8 +2048,16 @@ void SetObjectProperty::applyGs(CGameState * gs) const
{
auto * t = dynamic_cast<CGTownInstance *>(obj);
assert(t);
if(t->tempOwner < PlayerColor::PLAYER_LIMIT)
gs->getPlayerState(t->tempOwner)->towns -= t;
PlayerColor oldOwner = t->tempOwner;
if(oldOwner.isValidPlayer())
{
auto * state = gs->getPlayerState(oldOwner);
state->towns -= t;
if(state->towns.empty())
*state->daysWithoutCastle = 0;
}
if(val < PlayerColor::PLAYER_LIMIT_I)
{
PlayerState * p = gs->getPlayerState(PlayerColor(val));
@@ -2509,7 +2502,10 @@ void PlayerCheated::applyGs(CGameState * gs) const
void YourTurn::applyGs(CGameState * gs) const
{
gs->currentPlayer = player;
}
void DaysWithoutTown::applyGs(CGameState * gs) const
{
auto & playerState = gs->players[player];
playerState.daysWithoutCastle = daysWithoutCastle;
}
+1
View File
@@ -232,6 +232,7 @@ void registerTypesClientPacks1(Serializer &s)
s.template registerType<CPackForClient, PlayerBlocked>();
s.template registerType<CPackForClient, PlayerCheated>();
s.template registerType<CPackForClient, YourTurn>();
s.template registerType<CPackForClient, DaysWithoutTown>();
s.template registerType<CPackForClient, TurnTimeUpdate>();
s.template registerType<CPackForClient, SetResources>();
s.template registerType<CPackForClient, SetPrimSkill>();
+22 -1
View File
@@ -609,7 +609,28 @@ void CGameHandler::onPlayerTurnStarted(PlayerColor which)
void CGameHandler::onPlayerTurnEnded(PlayerColor which)
{
// 7 days without castle
const auto * playerState = gs->getPlayerState(which);
assert(playerState->status == EPlayerStatus::INGAME);
if (playerState->towns.empty())
{
DaysWithoutTown pack;
pack.player = which;
pack.daysWithoutCastle = playerState->daysWithoutCastle.value_or(0) + 1;
sendAndApply(&pack);
}
else
{
if (playerState->daysWithoutCastle.has_value())
{
DaysWithoutTown pack;
pack.player = which;
pack.daysWithoutCastle = std::nullopt;
sendAndApply(&pack);
}
}
// check for 7 days without castle
checkVictoryLossConditionsForPlayer(which);
bool newWeek = getDate(Date::DAY_OF_WEEK) == 7; // end of 7th day
+1 -1
View File
@@ -84,7 +84,7 @@ void TurnTimerHandler::onPlayerMakingTurn(PlayerState & state, int waitTime)
state.turnTimer.baseTimer = 0;
onPlayerMakingTurn(state, waitTime);
}
else if(!gameHandler.queries->topQuery(state.color))
else if(!gameHandler.queries->topQuery(state.color)) //wait for replies to avoid pending queries
gameHandler.turnOrder->onPlayerEndsTurn(state.color);
}
}
+5 -3
View File
@@ -100,8 +100,6 @@ void TurnOrderProcessor::doStartPlayerTurn(PlayerColor which)
YourTurn yt;
yt.player = 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 :(
@@ -111,6 +109,7 @@ void TurnOrderProcessor::doStartPlayerTurn(PlayerColor which)
void TurnOrderProcessor::doEndPlayerTurn(PlayerColor which)
{
assert(playerMakingTurn(which));
assert(gameHandler->getPlayerStatus(which) == EPlayerStatus::INGAME);
actingPlayers.erase(which);
actedPlayers.insert(which);
@@ -170,7 +169,10 @@ bool TurnOrderProcessor::onPlayerEndsTurn(PlayerColor which)
gameHandler->onPlayerTurnEnded(which);
doEndPlayerTurn(which);
// it is possible that player have lost - e.g. spent 7 days without town
// in this case - don't call doEndPlayerTurn - turn transfer was already handled by onPlayerEndsGame
if(gameHandler->getPlayerStatus(which) == EPlayerStatus::INGAME)
doEndPlayerTurn(which);
return true;
}
+7 -10
View File
@@ -37,6 +37,10 @@ class TurnOrderProcessor : boost::noncopyable
void doStartPlayerTurn(PlayerColor which);
void doEndPlayerTurn(PlayerColor which);
bool playerAwaitsTurn(PlayerColor which) const;
bool playerMakingTurn(PlayerColor which) const;
bool playerAwaitsNewDay(PlayerColor which) const;
public:
TurnOrderProcessor(CGameHandler * owner);
@@ -46,21 +50,14 @@ public:
/// NetPack call-in
bool onPlayerEndsTurn(PlayerColor which);
/// Ends player turn and removes this player from turn order
void onPlayerEndsGame(PlayerColor which);
/// Start game (or resume from save) and send YourTurn pack to player(s)
void onGameStarted();
/// Returns true if player turn has not started today
bool playerAwaitsTurn(PlayerColor which) const;
/// Returns true if player is currently making his turn
bool playerMakingTurn(PlayerColor which) const;
/// Returns true if player has finished his turn and is waiting for new day
bool playerAwaitsNewDay(PlayerColor which) const;
template <typename Handler> void serialize(Handler &h, const int version)
template<typename Handler>
void serialize(Handler & h, const int version)
{
h & awaitingPlayers;
h & actingPlayers;