Esempio n. 1
0
possible_end_play_signal playsingle_controller::play_scenario_main_loop(end_level_data & end_level, bool & /*past_prestart*/) {
    LOG_NG << "starting main loop\n" << (SDL_GetTicks() - ticks_) << "\n";

    // Initialize countdown clock.
    std::vector<team>::const_iterator t;
    for(t = gamestate_.board_.teams().begin(); t != gamestate_.board_.teams().end(); ++t) {
        if (saved_game_.mp_settings().mp_countdown && !loading_game_ ) {
            t->set_countdown_time(1000 * saved_game_.mp_settings().mp_countdown_init_time);
        }
    }

    // if we loaded a save file in linger mode, skip to it.
    if (linger_) {
        //determine the bonus gold handling for this scenario
        end_level.read(level_.child_or_empty("end_level_data"));
        end_level.transient.carryover_report = false;
        end_level.transient.disabled = true;
        end_level_struct els = { SKIP_TO_LINGER };
        return possible_end_play_signal ( els );
        //throw end_level_exception(SKIP_TO_LINGER);
    }

    // Avoid autosaving after loading, but still
    // allow the first turn to have an autosave.
    do_autosaves_ = !loading_game_;
    ai_testing::log_game_start();
    for(; ; first_player_ = 1) {
        PROPOGATE_END_PLAY_SIGNAL( play_turn() );
        do_autosaves_ = true;
    } //end for loop
    return boost::none;
}
possible_end_play_signal replay_controller::play_replay_main_loop() {
	DBG_REPLAY << "starting main loop\n" << (SDL_GetTicks() - ticks_) << "\n";
	for(; !recorder.at_end() && is_playing_; first_player_ = 1) {
		PROPOGATE_END_PLAY_SIGNAL ( play_turn() );
	}
	return boost::none;
}
possible_end_play_signal replay_controller::try_run_to_completion() {
	for (;;) {
		HANDLE_END_PLAY_SIGNAL( play_slice() );
		if (recorder.at_end()) {
			return boost::none;
		} else {
			if (!is_playing_) {
				PROPOGATE_END_PLAY_SIGNAL( play_replay() );
			}
		}
	}
}
possible_end_play_signal replay_controller::replay_next_turn(){
	is_playing_ = true;
	replay_ui_playback_should_start();

	PROPOGATE_END_PLAY_SIGNAL( play_turn() );

 	if (!skip_replay_ || !is_playing_){
		gui_->scroll_to_leader(player_number_,game_display::ONSCREEN,false);
	}

	replay_ui_playback_should_stop();
	return boost::none;
}
//make all sides move, then stop
possible_end_play_signal replay_controller::play_turn(){

	LOG_REPLAY << "turn: " << current_turn_ << "\n";

	gui_->new_turn();
	gui_->invalidate_game_status();
	events::raise_draw_event();

	bool last_team = false;

	while ( (!last_team) && (!recorder.at_end()) && is_playing_ ){
		last_team = static_cast<size_t>(player_number_) == gamestate_.board_.teams().size();
		PROPOGATE_END_PLAY_SIGNAL( play_side() );
		HANDLE_END_PLAY_SIGNAL( play_slice() );
	}
	return boost::none;
}
Esempio n. 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;
}
Esempio n. 7
0
possible_end_play_signal playsingle_controller::play_turn()
{
    whiteboard_manager_->on_gamestate_change();
    gui_->new_turn();
    gui_->invalidate_game_status();
    events::raise_draw_event();

    LOG_NG << "turn: " << turn() << "\n";

    if(non_interactive()) {
        LOG_AIT << "Turn " << turn() << ":" << std::endl;
    }

    for (player_number_ = first_player_; player_number_ <= int(gamestate_.board_.teams().size()); ++player_number_)
    {
        // If a side is empty skip over it.
        if (current_team().is_empty()) continue;

        possible_end_play_signal signal;
        {
            save_blocker blocker;
            signal = init_side();
        }

        if (signal) {
            switch (boost::apply_visitor(get_signal_type(), *signal)) {
            case END_TURN:
                if (current_team().is_network() == false) {
                    turn_data_.send_data();
                    recorder.end_turn();
                    turn_data_.sync_network();
                }
                continue;
            case END_LEVEL:
                return signal;
            }
        }

        if (replaying_) {
            LOG_NG << "doing replay " << player_number_ << "\n";
            HANDLE_END_PLAY_SIGNAL ( replaying_ = ::do_replay() == REPLAY_FOUND_END_TURN );
            LOG_NG << "result of replay: " << (replaying_?"true":"false") << "\n";
        } else {
            ai_testing::log_turn_start(player_number_);
            PROPOGATE_END_PLAY_SIGNAL ( play_side() );
        }

        finish_side_turn();

        if(non_interactive()) {
            LOG_AIT << " Player " << player_number_ << ": " <<
                    current_team().villages().size() << " Villages" <<
                    std::endl;
            ai_testing::log_turn_end(player_number_);
        }

        HANDLE_END_PLAY_SIGNAL ( check_victory() );

        //if loading a savegame, network turns might not have reset this yet
        loading_game_ = false;
    }
    //If the loop exits due to the last team having been processed,
    //player_number_ will be 1 too high
    if(player_number_ > static_cast<int>(gamestate_.board_.teams().size()))
        player_number_ = gamestate_.board_.teams().size();

    finish_turn();

    // Time has run out
    PROPOGATE_END_PLAY_SIGNAL ( check_time_over() );
    return boost::none;
}
Esempio n. 8
0
possible_end_play_signal playmp_controller::before_human_turn(){
	LOG_NG << "playmp::before_human_turn...\n";
	PROPOGATE_END_PLAY_SIGNAL( playsingle_controller::before_human_turn() );
	turn_data_.send_data();
	return boost::none;
}