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);
		}
	}
}
Example #3
0
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;
}
Example #6
0
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;
}
Example #7
0
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;
}
Example #8
0
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";
}