From e01ef8e36afb625f5310a01e6f3f5de6a568d7d9 Mon Sep 17 00:00:00 2001 From: beegee1 Date: Sat, 9 Nov 2013 16:25:20 +0000 Subject: [PATCH] - Fixed mantis #1576 (doesn't hang game) - Implemented output stream operator<< for various classes(BattleAction, BattleHex,...) to improve debugging and logging --- client/Client.cpp | 1 + client/battle/CBattleInterface.cpp | 23 +++++++++++++++++++---- lib/BattleAction.cpp | 9 +++++++++ lib/BattleAction.h | 2 ++ lib/BattleHex.cpp | 5 +++++ lib/BattleHex.h | 4 +++- lib/GameConstants.cpp | 25 +++++++++++++++++++++++++ lib/GameConstants.h | 2 ++ 8 files changed, 66 insertions(+), 5 deletions(-) diff --git a/client/Client.cpp b/client/Client.cpp index ea9f3da37..76776f759 100644 --- a/client/Client.cpp +++ b/client/Client.cpp @@ -118,6 +118,7 @@ void CClient::waitForMoveAndSend(PlayerColor color) setThreadName("CClient::waitForMoveAndSend"); assert(vstd::contains(battleints, color)); BattleAction ba = battleints[color]->activeStack(gs->curB->battleGetStackByID(gs->curB->activeStack, false)); + logNetwork->traceStream() << "Send battle action to server: " << ba; MakeAction temp_action(ba); sendRequest(&temp_action, color); return; diff --git a/client/battle/CBattleInterface.cpp b/client/battle/CBattleInterface.cpp index 7c72d2259..591988734 100644 --- a/client/battle/CBattleInterface.cpp +++ b/client/battle/CBattleInterface.cpp @@ -118,12 +118,14 @@ CBattleInterface::CBattleInterface(const CCreatureSet * army1, const CCreatureSe strongInterest = true; givenCommand = new CondSh(nullptr); - if(attackerInt && attackerInt->cb->battleGetTacticDist()) //hot-seat -> check tactics for both players (defender may be local human) + //hot-seat -> check tactics for both players (defender may be local human) + if(attackerInt && attackerInt->cb->battleGetTacticDist()) tacticianInterface = attackerInt; else if(defenderInt && defenderInt->cb->battleGetTacticDist()) tacticianInterface = defenderInt; - tacticsMode = static_cast(tacticianInterface); //if we found interface of player with tactics, then enter tactics mode + //if we found interface of player with tactics, then enter tactics mode + tacticsMode = static_cast(tacticianInterface); //create stack queue bool embedQueue = screen->h < 700; @@ -2848,11 +2850,24 @@ void CBattleInterface::requestAutofightingAIToTakeAction() boost::thread aiThread([&] { - auto ba = new BattleAction(curInt->autofightingAI->activeStack(activeStack)); + auto ba = new BattleAction(curInt->autofightingAI->activeStack(activeStack)); if(curInt->isAutoFightOn) { - givenCommand->setn(ba); + if(tacticsMode) + { + // Always end tactics mode. Player interface is blocked currently, so it's not possible that + // the AI can take any action except end tactics phase (AI actions won't be triggered) + //TODO implement the possibility that the AI will be triggered for further actions + //TODO any solution to merge tactics phase & normal phase in the way it is handled by the player and battle interface? + setActiveStack(nullptr); + blockUI(true); + tacticsMode = false; + } + else + { + givenCommand->setn(ba); + } } else { diff --git a/lib/BattleAction.cpp b/lib/BattleAction.cpp index 42cd95127..2cda10d59 100644 --- a/lib/BattleAction.cpp +++ b/lib/BattleAction.cpp @@ -92,3 +92,12 @@ BattleAction BattleAction::makeEndOFTacticPhase(ui8 side) ba.actionType = END_TACTIC_PHASE; return ba; } + +std::ostream & operator<<(std::ostream & os, const BattleAction & ba) +{ + std::stringstream actionTypeStream; + actionTypeStream << ba.actionType; + + return os << boost::str(boost::format("[BattleAction: side '%d', stackNumber '%d', actionType '%s', destinationTile '%s', additionalInfo '%d', selectedStack '%d']") + % static_cast(ba.side) % ba.stackNumber % actionTypeStream.str() % ba.destinationTile % ba.additionalInfo % ba.selectedStack); +} diff --git a/lib/BattleAction.h b/lib/BattleAction.h index 4951c3537..9fc66a820 100644 --- a/lib/BattleAction.h +++ b/lib/BattleAction.h @@ -40,3 +40,5 @@ struct DLL_LINKAGE BattleAction static BattleAction makeMove(const CStack *stack, BattleHex dest); static BattleAction makeEndOFTacticPhase(ui8 side); }; + +std::ostream & operator<<(std::ostream & os, const BattleAction & ba); diff --git a/lib/BattleHex.cpp b/lib/BattleHex.cpp index 883d81a2d..362a4ae8a 100644 --- a/lib/BattleHex.cpp +++ b/lib/BattleHex.cpp @@ -158,3 +158,8 @@ BattleHex BattleHex::getClosestTile(bool attackerOwned, BattleHex initialPos, st return sortedTiles.front(); } + +std::ostream & operator<<(std::ostream & os, const BattleHex & hex) +{ + return os << boost::str(boost::format("[BattleHex: x '%d', y '%d', hex '%d']") % hex.getX() % hex.getY() % hex.hex); +} diff --git a/lib/BattleHex.h b/lib/BattleHex.h index a9c59bd1c..f29a7dc19 100644 --- a/lib/BattleHex.h +++ b/lib/BattleHex.h @@ -112,4 +112,6 @@ struct DLL_LINKAGE BattleHex bool isAvailable() const; //valid position not in first or last column static BattleHex getClosestTile(bool attackerOwned, BattleHex initialPos, std::set & possibilities); //TODO: vector or set? copying one to another is bad -}; \ No newline at end of file +}; + +std::ostream & operator<<(std::ostream & os, const BattleHex & hex); diff --git a/lib/GameConstants.cpp b/lib/GameConstants.cpp index 61d836a67..56189053b 100644 --- a/lib/GameConstants.cpp +++ b/lib/GameConstants.cpp @@ -103,3 +103,28 @@ bool PlayerColor::isValidPlayer() const { return num < PLAYER_LIMIT_I; } + +std::ostream & operator<<(std::ostream & os, const Battle::ActionType actionType) +{ + static const std::map actionTypeToString = boost::assign::map_list_of + (Battle::END_TACTIC_PHASE, "End tactic phase") + (Battle::INVALID, "Invalid") + (Battle::NO_ACTION, "No action") + (Battle::HERO_SPELL, "Hero spell") + (Battle::WALK, "Walk") + (Battle::DEFEND, "Defend") + (Battle::RETREAT, "Retreat") + (Battle::SURRENDER, "Surrender") + (Battle::WALK_AND_ATTACK, "Walk and attack") + (Battle::SHOOT, "Shoot") + (Battle::WAIT, "Wait") + (Battle::CATAPULT, "Catapult") + (Battle::MONSTER_SPELL, "Monster spell") + (Battle::BAD_MORALE, "Bad morale") + (Battle::STACK_HEAL, "Stack heal") + (Battle::DAEMON_SUMMONING, "Daemon summoning"); + + auto it = actionTypeToString.find(actionType); + if (it == actionTypeToString.end()) return os << ""; + else return os << it->second; +} diff --git a/lib/GameConstants.h b/lib/GameConstants.h index 73c585eae..4bb5180ff 100644 --- a/lib/GameConstants.h +++ b/lib/GameConstants.h @@ -682,6 +682,8 @@ namespace Battle }; } +std::ostream & operator<<(std::ostream & os, const Battle::ActionType actionType); + class ETerrainType { public: