1
0
mirror of https://github.com/vcmi/vcmi.git synced 2025-02-03 13:01:33 +02:00

#1228 - prevent second AI activation on AI defeat due to wrong EndTurn packet

This commit is contained in:
Andrii Danylchenko 2022-12-14 22:13:26 +02:00
parent bd7f78b8d5
commit 56bf8ec2c4
6 changed files with 36 additions and 2 deletions

View File

@ -535,6 +535,7 @@ void AIGateway::yourTurn()
LOG_TRACE(logAi); LOG_TRACE(logAi);
NET_EVENT_HANDLER; NET_EVENT_HANDLER;
status.startedTurn(); status.startedTurn();
makingTurn = make_unique<boost::thread>(&AIGateway::makeTurn, this); makingTurn = make_unique<boost::thread>(&AIGateway::makeTurn, this);
} }
@ -1428,7 +1429,15 @@ void AIGateway::endTurn()
{ {
logAi->error("Not having turn at the end of turn???"); logAi->error("Not having turn at the end of turn???");
} }
logAi->debug("Resources at the end of turn: %s", cb->getResourceAmount().toString()); logAi->debug("Resources at the end of turn: %s", cb->getResourceAmount().toString());
if(cb->getPlayerStatus(playerID) != EPlayerStatus::INGAME)
{
logAi->info("Ending turn is not needed because we already lost");
return;
}
do do
{ {
cb->endTurn(); cb->endTurn();
@ -1601,7 +1610,7 @@ void AIStatus::waitTillFree()
{ {
boost::unique_lock<boost::mutex> lock(mx); boost::unique_lock<boost::mutex> lock(mx);
while(battle != NO_BATTLE || !remainingQueries.empty() || !objectsBeingVisited.empty() || ongoingHeroMovement) while(battle != NO_BATTLE || !remainingQueries.empty() || !objectsBeingVisited.empty() || ongoingHeroMovement)
cv.timed_wait(lock, boost::posix_time::milliseconds(100)); cv.timed_wait(lock, boost::posix_time::milliseconds(10));
} }
bool AIStatus::haveTurn() bool AIStatus::haveTurn()

View File

@ -74,6 +74,8 @@ Goals::TTask Nullkiller::choseBestTask(Goals::TTaskVec & tasks) const
Goals::TTask Nullkiller::choseBestTask(Goals::TSubgoal behavior, int decompositionMaxDepth) const Goals::TTask Nullkiller::choseBestTask(Goals::TSubgoal behavior, int decompositionMaxDepth) const
{ {
boost::this_thread::interruption_point();
logAi->debug("Checking behavior %s", behavior->toString()); logAi->debug("Checking behavior %s", behavior->toString());
auto start = std::chrono::high_resolution_clock::now(); auto start = std::chrono::high_resolution_clock::now();
@ -160,8 +162,12 @@ void Nullkiller::updateAiState(int pass, bool fast)
cfg.mainTurnDistanceLimit = MAIN_TURN_DISTANCE_LIMIT * ((int)scanDepth + 1); cfg.mainTurnDistanceLimit = MAIN_TURN_DISTANCE_LIMIT * ((int)scanDepth + 1);
} }
boost::this_thread::interruption_point();
pathfinder->updatePaths(activeHeroes, cfg); pathfinder->updatePaths(activeHeroes, cfg);
boost::this_thread::interruption_point();
objectClusterizer->clusterize(); objectClusterizer->clusterize();
} }
@ -212,6 +218,8 @@ HeroLockedReason Nullkiller::getHeroLockedReason(const CGHeroInstance * hero) co
void Nullkiller::makeTurn() void Nullkiller::makeTurn()
{ {
boost::lock_guard<boost::mutex> sharedStorageLock(AISharedStorage::locker);
const int MAX_DEPTH = 10; const int MAX_DEPTH = 10;
resetAiState(); resetAiState();

View File

@ -23,6 +23,7 @@ namespace NKAI
{ {
std::shared_ptr<boost::multi_array<AIPathNode, 5>> AISharedStorage::shared; std::shared_ptr<boost::multi_array<AIPathNode, 5>> AISharedStorage::shared;
boost::mutex AISharedStorage::locker;
std::set<int3> commitedTiles; std::set<int3> commitedTiles;
std::set<int3> commitedTilesInitial; std::set<int3> commitedTilesInitial;

View File

@ -135,6 +135,8 @@ class AISharedStorage
static std::shared_ptr<boost::multi_array<AIPathNode, 5>> shared; static std::shared_ptr<boost::multi_array<AIPathNode, 5>> shared;
std::shared_ptr<boost::multi_array<AIPathNode, 5>> nodes; std::shared_ptr<boost::multi_array<AIPathNode, 5>> nodes;
public: public:
static boost::mutex locker;
AISharedStorage(int3 mapSize); AISharedStorage(int3 mapSize);
~AISharedStorage(); ~AISharedStorage();

View File

@ -80,6 +80,8 @@ void AIPathfinder::updatePaths(std::map<const CGHeroInstance *, HeroRole> heroes
do do
{ {
boost::this_thread::interruption_point();
while(storage->calculateHeroChain()) while(storage->calculateHeroChain())
{ {
boost::this_thread::interruption_point(); boost::this_thread::interruption_point();
@ -91,6 +93,8 @@ void AIPathfinder::updatePaths(std::map<const CGHeroInstance *, HeroRole> heroes
logAi->trace("Select next actor"); logAi->trace("Select next actor");
} while(storage->selectNextActor()); } while(storage->selectNextActor());
boost::this_thread::interruption_point();
if(storage->calculateHeroChainFinal()) if(storage->calculateHeroChainFinal())
{ {
boost::this_thread::interruption_point(); boost::this_thread::interruption_point();

View File

@ -89,7 +89,17 @@ bool SaveGame::applyGh(CGameHandler * gh)
bool EndTurn::applyGh(CGameHandler * gh) bool EndTurn::applyGh(CGameHandler * gh)
{ {
PlayerColor player = GS(gh)->currentPlayer; PlayerColor currentPlayer = GS(gh)->currentPlayer;
if(player != currentPlayer)
{
if(gh->getPlayerStatus(player) == EPlayerStatus::INGAME)
throwAndComplain(gh, "Player attempted to end turn for another player!");
logGlobal->debug("Player attempted to end turn after game over. Ignoring this request.");
return true;
}
throwOnWrongPlayer(gh, player); throwOnWrongPlayer(gh, player);
if(gh->queries.topQuery(player)) if(gh->queries.topQuery(player))
throwAndComplain(gh, "Cannot end turn before resolving queries!"); throwAndComplain(gh, "Cannot end turn before resolving queries!");