boost::statechart::result WaitingForTurnData::react(const TurnUpdate& msg) { TraceLogger(FSM) << "(HumanClientFSM) PlayingGame.TurnUpdate"; int current_turn = INVALID_GAME_TURN; try { ExtractTurnUpdateMessageData(msg.m_message, Client().EmpireID(), current_turn, Empires(), GetUniverse(), GetSpeciesManager(), GetCombatLogManager(), GetSupplyManager(), Client().Players()); } catch (...) { Client().GetClientUI().GetMessageWnd()->HandleLogMessage(UserString("ERROR_PROCESSING_SERVER_MESSAGE") + "\n"); return discard_event(); } DebugLogger(FSM) << "Extracted TurnUpdate message for turn: " << current_turn; Client().SetCurrentTurn(current_turn); // if I am the host, do autosave if (Client().Networking().PlayerIsHost(Client().PlayerID())) Client().Autosave(); Client().HandleTurnUpdate(); return transit<PlayingTurn>(); }
boost::statechart::result WaitingForGameStart::react(const GameStart& msg) { TraceLogger(FSM) << "(HumanClientFSM) WaitingForGameStart.GameStart"; bool loaded_game_data; bool ui_data_available; SaveGameUIData ui_data; bool save_state_string_available; std::string save_state_string; // ignored - used by AI but not by human client OrderSet orders; bool single_player_game = false; int empire_id = ALL_EMPIRES; int current_turn = INVALID_GAME_TURN; Client().PlayerStatus().clear(); Client().Orders().Reset(); ExtractGameStartMessageData(msg.m_message, single_player_game, empire_id, current_turn, Empires(), GetUniverse(), GetSpeciesManager(), GetCombatLogManager(), GetSupplyManager(), Client().Players(), Client().Orders(), loaded_game_data, ui_data_available, ui_data, save_state_string_available, save_state_string, Client().GetGalaxySetupData()); DebugLogger(FSM) << "Extracted GameStart message for turn: " << current_turn << " with empire: " << empire_id; Client().SetSinglePlayerGame(single_player_game); Client().SetEmpireID(empire_id); Client().SetCurrentTurn(current_turn); GetGameRules().SetFromStrings(Client().GetGalaxySetupData().GetGameRules()); bool is_new_game = !(loaded_game_data && ui_data_available); Client().StartGame(is_new_game); if (!is_new_game) Client().GetClientUI().RestoreFromSaveData(ui_data); // if I am the host on the first turn, do an autosave. if (is_new_game && Client().Networking().PlayerIsHost(Client().PlayerID())) Client().Autosave(); return transit<PlayingTurn>(); }
boost::statechart::result WaitingForGameStart::react(const GameStart& msg) { if (TRACE_EXECUTION) DebugLogger() << "(HumanClientFSM) WaitingForGameStart.GameStart"; bool loaded_game_data; bool ui_data_available; SaveGameUIData ui_data; bool save_state_string_available; std::string save_state_string; // ignored - used by AI but not by human client OrderSet orders; bool single_player_game = false; int empire_id = ALL_EMPIRES; int current_turn = INVALID_GAME_TURN; Client().PlayerStatus().clear(); ExtractMessageData(msg.m_message, single_player_game, empire_id, current_turn, Empires(), GetUniverse(), GetSpeciesManager(), GetCombatLogManager(), GetSupplyManager(), Client().Players(), orders, loaded_game_data, ui_data_available, ui_data, save_state_string_available, save_state_string, Client().GetGalaxySetupData()); DebugLogger() << "Extracted GameStart message for turn: " << current_turn << " with empire: " << empire_id; Client().SetSinglePlayerGame(single_player_game); Client().SetEmpireID(empire_id); Client().SetCurrentTurn(current_turn); Client().StartGame(); std::swap(Client().Orders(), orders); // bring back orders planned in the current turn, they will be applied later, after some basic turn initialization if (loaded_game_data && ui_data_available) Client().GetClientUI()->RestoreFromSaveData(ui_data); // if I am the host on the first turn, do an autosave. on later turns, will // have just loaded save, so don't need to autosave. might also have just // loaded a turn 1 autosave, but not sure how to check for that here... if (Client().CurrentTurn() == 1 && Client().Networking().PlayerIsHost(Client().PlayerID())) Client().Autosave(); return transit<PlayingTurn>(); }
void AIClientApp::HandleMessage(const Message& msg) { //DebugLogger() << "AIClientApp::HandleMessage " << msg.Type(); switch (msg.Type()) { case Message::ERROR_MSG: { ErrorLogger() << "AIClientApp::HandleMessage : Received ERROR message from server: " << msg.Text(); break; } case Message::HOST_ID: { const std::string& text = msg.Text(); int host_id = Networking::INVALID_PLAYER_ID; if (text.empty()) { ErrorLogger() << "AIClientApp::HandleMessage for HOST_ID : Got empty message text?!"; } else { try { host_id = boost::lexical_cast<int>(text); } catch(const boost::bad_lexical_cast& ex) { ErrorLogger() << "AIClientApp::HandleMessage for HOST_ID : Couldn't parse message text \"" << text << "\": " << ex.what(); } } m_networking->SetHostPlayerID(host_id); break; } case Message::JOIN_GAME: { if (PlayerID() == Networking::INVALID_PLAYER_ID) { DebugLogger() << "AIClientApp::HandleMessage : Received JOIN_GAME acknowledgement"; try { int player_id; boost::uuids::uuid cookie; // ignore ExtractJoinAckMessageData(msg, player_id, cookie); m_networking->SetPlayerID(player_id); } catch(const boost::bad_lexical_cast& ex) { ErrorLogger() << "AIClientApp::HandleMessage for JOIN_GAME : Couldn't parse message text \"" << msg.Text() << "\": " << ex.what(); } } else { ErrorLogger() << "AIClientApp::HandleMessage : Received erroneous JOIN_GAME acknowledgement when already in a game"; } break; } case Message::GAME_START: { DebugLogger() << "AIClientApp::HandleMessage : Received GAME_START message; starting AI turn..."; bool single_player_game; // ignored bool loaded_game_data; bool ui_data_available; // ignored SaveGameUIData ui_data; // ignored bool state_string_available; // ignored, as save_state_string is sent even if not set by ExtractMessageData std::string save_state_string; m_empire_status.clear(); ExtractGameStartMessageData(msg, single_player_game, m_empire_id, m_current_turn, m_empires, m_universe, GetSpeciesManager(), GetCombatLogManager(), GetSupplyManager(), m_player_info, m_orders, loaded_game_data, ui_data_available, ui_data, state_string_available, save_state_string, m_galaxy_setup_data); DebugLogger() << "Extracted GameStart message for turn: " << m_current_turn << " with empire: " << m_empire_id; GetUniverse().InitializeSystemGraph(m_empire_id); DebugLogger() << "Message::GAME_START loaded_game_data: " << loaded_game_data; if (loaded_game_data) { TraceLogger() << "Message::GAME_START save_state_string: " << save_state_string; m_AI->ResumeLoadedGame(save_state_string); Orders().ApplyOrders(); } else { DebugLogger() << "Message::GAME_START Starting New Game!"; // % Distribution of aggression levels // Aggression : 0 1 2 3 4 5 (0=Beginner, 5=Maniacal) // __ __ __ __ __ __ //Max 0 :100 0 0 0 0 0 //Max 1 : 25 75 0 0 0 0 //Max 2 : 0 25 75 0 0 0 //Max 3 : 0 0 25 75 0 0 //Max 4 : 0 0 0 25 75 0 //Max 5 : 0 0 0 0 25 75 // Optional aggression table, possibly for 0.4.4+? // Aggression : 0 1 2 3 4 5 (0=Beginner, 5=Maniacal) // __ __ __ __ __ __ //Max 0 :100 0 0 0 0 0 //Max 1 : 25 75 0 0 0 0 //Max 2 : 8 17 75 0 0 0 //Max 3 : 0 8 17 75 0 0 //Max 4 : 0 0 8 17 75 0 //Max 5 : 0 0 0 8 17 75 const std::string g_seed = GetGalaxySetupData().m_seed; const std::string emp_name = GetEmpire(m_empire_id)->Name(); unsigned int my_seed = 0; try { // generate consistent my_seed values from galaxy seed & empire name. boost::hash<std::string> string_hash; std::size_t h = string_hash(g_seed); my_seed = 3 * static_cast<unsigned int>(h) * static_cast<unsigned int>(string_hash(emp_name)); DebugLogger() << "Message::GAME_START getting " << emp_name << " AI aggression, RNG Seed: " << my_seed; } catch (...) { DebugLogger() << "Message::GAME_START getting " << emp_name << " AI aggression, could not initialise RNG."; } int rand_num = 0; int this_aggr = m_max_aggression; if (this_aggr > 0 && my_seed > 0) { Seed(my_seed); rand_num = RandSmallInt(0, 99); // if it's in the top 25% then decrease aggression. if (rand_num > 74) this_aggr--; // Leaving the following as commented out code for now. Possibly for 0.4.4+? // in the top 8% ? decrease aggression again, unless it's already as low as it gets. // if (rand_num > 91 && this_aggr > 0) this_aggr--; } DebugLogger() << "Message::GAME_START setting AI aggression as " << this_aggr << " (from rnd " << rand_num << "; max aggression " << m_max_aggression << ")"; m_AI->SetAggression(this_aggr); m_AI->StartNewGame(); } m_AI->GenerateOrders(); break; } case Message::SAVE_GAME_COMPLETE: break; case Message::TURN_UPDATE: { //DebugLogger() << "AIClientApp::HandleMessage : extracting turn update message data"; ExtractTurnUpdateMessageData(msg, m_empire_id, m_current_turn, m_empires, m_universe, GetSpeciesManager(), GetCombatLogManager(), GetSupplyManager(), m_player_info); //DebugLogger() << "AIClientApp::HandleMessage : generating orders"; GetUniverse().InitializeSystemGraph(m_empire_id); m_AI->GenerateOrders(); //DebugLogger() << "AIClientApp::HandleMessage : done handling turn update message"; break; } case Message::TURN_PARTIAL_UPDATE: ExtractTurnPartialUpdateMessageData(msg, m_empire_id, m_universe); break; case Message::TURN_PROGRESS: { Message::TurnProgressPhase phase_id; ExtractTurnProgressMessageData(msg, phase_id); ClientApp::HandleTurnPhaseUpdate(phase_id); break; } case Message::PLAYER_STATUS: break; case Message::END_GAME: { DebugLogger() << "Message::END_GAME : Exiting"; DebugLogger() << "Acknowledge server shutdown message."; Networking().SendMessage(AIEndGameAcknowledgeMessage()); ExitApp(0); break; } case Message::PLAYER_CHAT: { std::string data; int player_id; boost::posix_time::ptime timestamp; ExtractServerPlayerChatMessageData(msg, player_id, timestamp, data); m_AI->HandleChatMessage(player_id, data); break; } case Message::DIPLOMACY: { DiplomaticMessage diplo_message; ExtractDiplomacyMessageData(msg, diplo_message); m_AI->HandleDiplomaticMessage(diplo_message); break; } case Message::DIPLOMATIC_STATUS: { DiplomaticStatusUpdateInfo diplo_update; ExtractDiplomaticStatusMessageData(msg, diplo_update); m_AI->HandleDiplomaticStatusUpdate(diplo_update); break; } case Message::LOGGER_CONFIG: { std::set<std::tuple<std::string, std::string, LogLevel>> options; ExtractLoggerConfigMessageData(msg, options); SetLoggerThresholds(options); break; } case Message::CHECKSUM: { TraceLogger() << "(AIClientApp) CheckSum."; VerifyCheckSum(msg); break; } default: { ErrorLogger() << "AIClientApp::HandleMessage : Received unknown Message type code " << msg.Type(); break; } } //DebugLogger() << "AIClientApp::HandleMessage done"; }