void playsingle_controller::play_side(const unsigned int side_number, bool save) { //check for team-specific items in the scenario gui_->parse_team_overlays(); //flag used when we fallback from ai and give temporarily control to human bool temporary_human = false; do { // Although this flag is used only in this method, // it has to be a class member since derived classes // rely on it player_type_changed_ = false; if (!skip_next_turn_) end_turn_ = false; statistics::reset_turn_stats(teams_[side_number - 1].save_id()); if(current_team().is_human() || temporary_human) { LOG_NG << "is human...\n"; try{ before_human_turn(save); play_human_turn(); after_human_turn(); } catch(end_turn_exception& end_turn) { if (end_turn.redo == side_number) { player_type_changed_ = true; // If new controller is not human, // reset gui to prev human one if (!teams_[side_number-1].is_human()) { browse_ = true; int t = find_human_team_before(side_number); if (t > 0) { update_gui_to_player(t-1); } } } } LOG_NG << "human finished turn...\n"; } else if(current_team().is_ai()) { try { play_ai_turn(); } catch(fallback_ai_to_human_exception&) { //give control to human for the rest of this turn player_type_changed_ = true; temporary_human = true; } } } while (player_type_changed_); // Keep looping if the type of a team (human/ai/networked) // has changed mid-turn skip_next_turn_ = false; }
void playsingle_controller::update_viewing_player() { if(replay_ && replay_->is_controlling_view()) { replay_->update_viewing_player(); } //Update viewing team in case it has changed during the loop. else if(int side_num = play_controller::find_last_visible_team()) { if(side_num != this->gui_->viewing_side()) { update_gui_to_player(side_num - 1); } } }
void play_controller::init_side_begin() { mouse_handler_.set_side(current_side()); // If we are observers we move to watch next team if it is allowed if ((is_observer() && !current_team().get_disallow_observers()) || (current_team().is_local_human() && !this->is_replay())) { update_gui_to_player(current_side() - 1); } gui_->set_playing_team(size_t(current_side() - 1)); gamestate().gamedata_.last_selected = map_location::null_location(); }
void playmp_controller::linger() { LOG_NG << "beginning end-of-scenario linger\n"; linger_ = true; // If we need to set the status depending on the completion state // we're needed here. gui_->set_game_mode(game_display::LINGER); // End all unit moves gamestate().board_.set_all_units_user_end_turn(); set_end_scenario_button(); assert(is_regular_game_end()); if ( get_end_level_data_const().transient.reveal_map ) { // Change the view of all players and observers // to see the whole map regardless of shroud and fog. update_gui_to_player(gui_->viewing_team(), true); } bool quit; do { quit = true; try { // reimplement parts of play_side() turn_data_.send_data(); end_turn_ = END_TURN_NONE; play_linger_turn(); after_human_turn(); LOG_NG << "finished human turn" << std::endl; } catch (const savegame::load_game_exception&) { LOG_NG << "caught load-game-exception" << std::endl; // this should not happen, the option to load a game is disabled throw; } catch (const ingame_wesnothd_error&) { LOG_NG << "caught network-error-exception" << std::endl; quit = false; } } while (!quit); reset_end_scenario_button(); LOG_NG << "ending end-of-scenario linger\n"; }
void playsingle_controller::play_side() { //check for team-specific items in the scenario gui_->parse_team_overlays(); maybe_do_init_side(); if(is_regular_game_end()) { return; } //flag used when we fallback from ai and give temporarily control to human bool temporary_human = false; do { //Update viewing team in case it has changed during the loop. if(int side_num = play_controller::find_last_visible_team()) { if(side_num != this->gui_->viewing_side()) { update_gui_to_player(side_num - 1); } } // This flag can be set by derived classes (in overridden functions). player_type_changed_ = false; if (!skip_next_turn_) end_turn_ = END_TURN_NONE; statistics::reset_turn_stats(gamestate_.board_.teams()[player_number_ - 1].save_id()); if((current_team().is_local_human() && current_team().is_proxy_human()) || temporary_human) { LOG_NG << "is human...\n"; temporary_human = false; // If a side is dead end the turn, but play at least side=1's // turn in case all sides are dead if (gamestate_.board_.side_units(player_number_) == 0 && !(gamestate_.board_.units().size() == 0 && player_number_ == 1)) { end_turn_ = END_TURN_REQUIRED; } before_human_turn(); if (end_turn_ == END_TURN_NONE) { play_human_turn(); } if(is_regular_game_end()) { return; } if ( !player_type_changed_ ) { after_human_turn(); } LOG_NG << "human finished turn...\n"; } else if(current_team().is_local_ai() || (current_team().is_local_human() && current_team().is_droid())) { try { play_ai_turn(); } catch(fallback_ai_to_human_exception&) { // Give control to a human for this turn. player_type_changed_ = true; temporary_human = true; } if(is_regular_game_end()) { return; } } else if(current_team().is_network()) { play_network_turn(); if(is_regular_game_end()) { return; } } else if(current_team().is_local_human() && current_team().is_idle()) { end_turn_enable(false); do_idle_notification(); before_human_turn(); if (end_turn_ == END_TURN_NONE) { play_idle_loop(); if(is_regular_game_end()) { return; } } } else { assert(current_team().is_empty()); // Do nothing. } } while (player_type_changed_); // Keep looping if the type of a team (human/ai/networked) // has changed mid-turn sync_end_turn(); assert(end_turn_ == END_TURN_SYNCED); skip_next_turn_ = false; }
possible_end_play_signal playsingle_controller::play_side() { //check for team-specific items in the scenario gui_->parse_team_overlays(); HANDLE_END_PLAY_SIGNAL( maybe_do_init_side(false) ); //flag used when we fallback from ai and give temporarily control to human bool temporary_human = false; do { // This flag can be set by derived classes (in overridden functions). player_type_changed_ = false; if (!skip_next_turn_) end_turn_ = false; statistics::reset_turn_stats(gamestate_.board_.teams()[player_number_ - 1].save_id()); if(current_team().is_human() || temporary_human) { LOG_NG << "is human...\n"; temporary_human = false; // If a side is dead end the turn, but play at least side=1's // turn in case all sides are dead if (gamestate_.board_.side_units(player_number_) != 0 || (resources::units->size() == 0 && player_number_ == 1)) { possible_end_play_signal signal = before_human_turn(); if (!signal) { signal = play_human_turn(); } if (signal) { switch (boost::apply_visitor(get_signal_type(), *signal)) { case END_LEVEL: return signal; case END_TURN: if (int(boost::apply_visitor(get_redo(),*signal)) == player_number_) { player_type_changed_ = true; // If new controller is not human, // reset gui to prev human one if (!gamestate_.board_.teams()[player_number_-1].is_human()) { browse_ = true; int s = find_human_team_before_current_player(); if (s <= 0) s = gui_->playing_side(); update_gui_to_player(s-1); } } } } } // Ending the turn commits all moves. undo_stack_->clear(); if ( !player_type_changed_ ) after_human_turn(); LOG_NG << "human finished turn...\n"; } else if(current_team().is_ai()) { try { play_ai_turn(); } catch(fallback_ai_to_human_exception&) { // Give control to a human for this turn. player_type_changed_ = true; temporary_human = true; } catch (end_level_exception & e) { //Don't know at the moment if these two are possible but can't hurt to add return possible_end_play_signal(e.to_struct()); } catch (end_turn_exception & e) { return possible_end_play_signal(e.to_struct()); } if(!player_type_changed_) { recorder.end_turn(); } } else if(current_team().is_network()) { PROPOGATE_END_PLAY_SIGNAL( play_network_turn() ); } else if(current_team().is_idle()) { end_turn_enable(false); do_idle_notification(); possible_end_play_signal signal = before_human_turn(); if (!signal) { signal = play_idle_loop(); } if (signal) { switch (boost::apply_visitor(get_signal_type(), *signal)) { case END_LEVEL: return signal; case END_TURN: LOG_NG << "Escaped from idle state with exception!" << std::endl; if (int(boost::apply_visitor(get_redo(), *signal)) == player_number_) { player_type_changed_ = true; // If new controller is not human, // reset gui to prev human one if (!gamestate_.board_.teams()[player_number_-1].is_human()) { browse_ = true; int s = find_human_team_before_current_player(); if (s <= 0) s = gui_->playing_side(); update_gui_to_player(s-1); } } } } } // Else current_team().is_empty(), so do nothing. } while (player_type_changed_); // Keep looping if the type of a team (human/ai/networked) // has changed mid-turn skip_next_turn_ = false; return boost::none; }
void playsingle_controller::play_side(const unsigned int side_number, bool save) { //check for team-specific items in the scenario gui_->parse_team_overlays(); //flag used when we fallback from ai and give temporarily control to human bool temporary_human = false; do { // This flag can be set by derived classes (in overridden functions). player_type_changed_ = false; if (!skip_next_turn_) end_turn_ = false; statistics::reset_turn_stats(teams_[side_number - 1].save_id()); if(current_team().is_human() || temporary_human) { LOG_NG << "is human...\n"; temporary_human = false; try{ before_human_turn(save); play_human_turn(); } catch(end_turn_exception& end_turn) { if (end_turn.redo == side_number) { player_type_changed_ = true; // If new controller is not human, // reset gui to prev human one if (!teams_[side_number-1].is_human()) { browse_ = true; int s = find_human_team_before(side_number); if (s <= 0) s = gui_->playing_side(); update_gui_to_player(s-1); } } } // Ending the turn commits all moves. undo_stack_->clear(); if ( !player_type_changed_ ) after_human_turn(); LOG_NG << "human finished turn...\n"; } else if(current_team().is_ai()) { try { play_ai_turn(); } catch(fallback_ai_to_human_exception&) { // Give control to a human for this turn. player_type_changed_ = true; temporary_human = true; } } else if(current_team().is_network()) { play_network_turn(); } // Else current_team().is_empty(), so do nothing. } while (player_type_changed_); // Keep looping if the type of a team (human/ai/networked) // has changed mid-turn skip_next_turn_ = false; }
void playmp_controller::linger() { LOG_NG << "beginning end-of-scenario linger\n"; browse_ = true; linger_ = true; // If we need to set the status depending on the completion state // we're needed here. gui_->set_game_mode(game_display::LINGER_MP); // this is actually for after linger mode is over -- we don't want to // stay stuck in linger state when the *next* scenario is over. set_completion setter(saved_game_,"running"); // End all unit moves gamestate_.board_.set_all_units_user_end_turn(); //current_team().set_countdown_time(0); //halt and cancel the countdown timer reset_countdown(); set_end_scenario_button(); if ( get_end_level_data_const().transient.reveal_map ) { // Change the view of all players and observers // to see the whole map regardless of shroud and fog. update_gui_to_player(gui_->viewing_team(), true); } bool quit; do { quit = true; try { // reimplement parts of play_side() player_number_ = first_player_; turn_data_.send_data(); end_turn_ = false; play_human_turn(); after_human_turn(); LOG_NG << "finished human turn" << std::endl; } catch (game::load_game_exception&) { LOG_NG << "caught load-game-exception" << std::endl; // this should not happen, the option to load a game is disabled throw; } catch (end_level_exception&) { // thrown if the host ends the scenario and let us advance // to the next level LOG_NG << "caught end-level-exception" << std::endl; reset_end_scenario_button(); throw; } catch (end_turn_exception&) { // thrown if the host leaves the game (sends [leave_game]), we need // to stay in this loop to stay in linger mode, otherwise the game // gets aborted LOG_NG << "caught end-turn-exception" << std::endl; quit = false; } catch (network::error&) { LOG_NG << "caught network-error-exception" << std::endl; quit = false; } } while (!quit); reset_end_scenario_button(); LOG_NG << "ending end-of-scenario linger\n"; }