TurnOrderProcessor.cpp 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183
  1. /*
  2. * TurnOrderProcessor.cpp, part of VCMI engine
  3. *
  4. * Authors: listed in file AUTHORS in main folder
  5. *
  6. * License: GNU General Public License v2.0 or later
  7. * Full text of license available in license.txt file, in main folder
  8. *
  9. */
  10. #include "StdInc.h"
  11. #include "TurnOrderProcessor.h"
  12. #include "../queries/QueriesProcessor.h"
  13. #include "../CGameHandler.h"
  14. #include "../CVCMIServer.h"
  15. #include "../../lib/CPlayerState.h"
  16. #include "../../lib/NetPacks.h"
  17. TurnOrderProcessor::TurnOrderProcessor(CGameHandler * owner):
  18. gameHandler(owner)
  19. {
  20. }
  21. bool TurnOrderProcessor::canActSimultaneously(PlayerColor active, PlayerColor waiting) const
  22. {
  23. return false;
  24. }
  25. bool TurnOrderProcessor::mustActBefore(PlayerColor left, PlayerColor right) const
  26. {
  27. const auto * leftInfo = gameHandler->getPlayerState(left, false);
  28. const auto * rightInfo = gameHandler->getPlayerState(right, false);
  29. assert(left != right);
  30. assert(leftInfo && rightInfo);
  31. if (!leftInfo)
  32. return false;
  33. if (!rightInfo)
  34. return true;
  35. if (leftInfo->isHuman() && !rightInfo->isHuman())
  36. return true;
  37. if (!leftInfo->isHuman() && rightInfo->isHuman())
  38. return false;
  39. return left < right;
  40. }
  41. bool TurnOrderProcessor::canStartTurn(PlayerColor which) const
  42. {
  43. for (auto player : awaitingPlayers)
  44. {
  45. if (mustActBefore(player, which))
  46. return false;
  47. }
  48. for (auto player : actingPlayers)
  49. {
  50. if (!canActSimultaneously(player, which))
  51. return false;
  52. }
  53. return true;
  54. }
  55. void TurnOrderProcessor::doStartNewDay()
  56. {
  57. assert(awaitingPlayers.empty());
  58. assert(actingPlayers.empty());
  59. bool activePlayer = false;
  60. for (auto player : actedPlayers)
  61. {
  62. if (gameHandler->getPlayerState(player)->status == EPlayerStatus::INGAME)
  63. activePlayer = true;
  64. }
  65. if(!activePlayer)
  66. gameHandler->gameLobby()->setState(EServerState::GAMEPLAY_ENDED);
  67. std::swap(actedPlayers, awaitingPlayers);
  68. }
  69. void TurnOrderProcessor::doStartPlayerTurn(PlayerColor which)
  70. {
  71. //if player runs out of time, he shouldn't get the turn (especially AI)
  72. //pre-trigger may change anything, should check before each player
  73. //TODO: is it enough to check only one player?
  74. gameHandler->checkVictoryLossConditionsForAll();
  75. assert(gameHandler->getPlayerState(which));
  76. assert(gameHandler->getPlayerState(which)->status == EPlayerStatus::INGAME);
  77. gameHandler->onPlayerTurnStarted(which);
  78. YourTurn yt;
  79. yt.player = which;
  80. //Change local daysWithoutCastle counter for local interface message //TODO: needed?
  81. yt.daysWithoutCastle = gameHandler->getPlayerState(which)->daysWithoutCastle;
  82. gameHandler->sendAndApply(&yt);
  83. }
  84. void TurnOrderProcessor::doEndPlayerTurn(PlayerColor which)
  85. {
  86. assert(playerMakingTurn(which));
  87. actingPlayers.erase(which);
  88. actedPlayers.insert(which);
  89. if (!awaitingPlayers.empty())
  90. tryStartTurnsForPlayers();
  91. if (actingPlayers.empty())
  92. doStartNewDay();
  93. }
  94. void TurnOrderProcessor::addPlayer(PlayerColor which)
  95. {
  96. awaitingPlayers.insert(which);
  97. }
  98. bool TurnOrderProcessor::onPlayerEndsTurn(PlayerColor which)
  99. {
  100. if (!playerMakingTurn(which))
  101. {
  102. gameHandler->complain("Can not end turn for player that is not acting!");
  103. return false;
  104. }
  105. if(gameHandler->getPlayerStatus(which) != EPlayerStatus::INGAME)
  106. {
  107. gameHandler->complain("Can not end turn for player that is not in game!");
  108. return false;
  109. }
  110. if(gameHandler->queries->topQuery(which) != nullptr)
  111. {
  112. gameHandler->complain("Cannot end turn before resolving queries!");
  113. return false;
  114. }
  115. doEndPlayerTurn(which);
  116. return true;
  117. }
  118. void TurnOrderProcessor::onGameStarted()
  119. {
  120. tryStartTurnsForPlayers();
  121. // this may be game load - send notification to players that they can act
  122. auto actingPlayersCopy = actingPlayers;
  123. for (auto player : actingPlayersCopy)
  124. doStartPlayerTurn(player);
  125. }
  126. void TurnOrderProcessor::tryStartTurnsForPlayers()
  127. {
  128. auto awaitingPlayersCopy = awaitingPlayers;
  129. for (auto player : awaitingPlayersCopy)
  130. {
  131. if (canStartTurn(player))
  132. doStartPlayerTurn(player);
  133. }
  134. }
  135. bool TurnOrderProcessor::playerAwaitsTurn(PlayerColor which) const
  136. {
  137. return vstd::contains(awaitingPlayers, which);
  138. }
  139. bool TurnOrderProcessor::playerMakingTurn(PlayerColor which) const
  140. {
  141. return vstd::contains(actingPlayers, which);
  142. }
  143. bool TurnOrderProcessor::playerAwaitsNewDay(PlayerColor which) const
  144. {
  145. return vstd::contains(actedPlayers, which);
  146. }