예제 #1
0
void play_controller::finish_side_turn()
{
    whiteboard_manager_->on_finish_side_turn(current_side());

    {   //Block for set_scontext_synced
        set_scontext_synced sync(1);
        // Ending the turn commits all moves.
        undo_stack().clear();
        gamestate().board_.end_turn(current_side());
        const std::string turn_num = std::to_string(turn());
        const std::string side_num = std::to_string(current_side());

        // Clear shroud, in case units had been slowed for the turn.
        actions::clear_shroud(current_side());

        pump().fire("side_turn_end");
        pump().fire("side_"+ side_num + "_turn_end");
        pump().fire("side_turn_" + turn_num + "_end");
        pump().fire("side_" + side_num + "_turn_" + turn_num + "_end");
        // This is where we refog, after all of a side's events are done.
        actions::recalculate_fog(current_side());
        check_victory();
        sync.do_final_checkup();
    }

    mouse_handler_.deselect_hex();
    resources::gameboard->unit_id_manager().reset_fake();
    gamestate_->init_side_done() = false;
}
예제 #2
0
int play_controller::find_last_visible_team() const
{
    assert(current_side() <= int(gamestate().board_.teams().size()));
    const int num_teams = gamestate().board_.teams().size();
    const bool is_observer = this->is_observer();

    for(int i = 0; i < num_teams; i++) {
        const int team_num = modulo(current_side() - i, num_teams, 1);
        if(is_team_visible(team_num, is_observer)) {
            return team_num;
        }
    }
    return 0;
}
예제 #3
0
void play_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(gui_->video().non_interactive()) {
        LOG_AIT << "Turn " << turn() << ":" << std::endl;
    }

    for (; gamestate_->player_number_ <= int(gamestate().board_.teams().size()); ++gamestate_->player_number_)
    {
        // If a side is empty skip over it.
        if (current_team().is_empty()) {
            continue;
        }
        init_side_begin();
        if(gamestate_->init_side_done()) {
            // This is the case in a reloaded game where the side was initialized before saving the game.
            init_side_end();
        }

        ai_testing::log_turn_start(current_side());
        play_side();
        if(is_regular_game_end()) {
            return;
        }
        finish_side_turn();
        if(is_regular_game_end()) {
            return;
        }
        if(gui_->video().non_interactive()) {
            LOG_AIT << " Player " << current_side() << ": " <<
                    current_team().villages().size() << " Villages" <<
                    std::endl;
            ai_testing::log_turn_end(current_side());
        }
    }
    // If the loop exits due to the last team having been processed.
    gamestate_->player_number_ = gamestate().board_.teams().size();

    finish_turn();

    // Time has run out
    check_time_over();
}
예제 #4
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();
}
예제 #5
0
void play_controller::init_side_end()
{
    const time_of_day& tod = gamestate().tod_manager_.get_time_of_day();

    if (current_side() == 1 || !init_side_done_now_)
        sound::play_sound(tod.sounds, sound::SOUND_SOURCES);

    if (!is_skipping_replay()) {
        gui_->invalidate_all();
    }

    if (!is_skipping_replay() && current_team().get_scroll_to_leader()) {
        gui_->scroll_to_leader(current_side(), game_display::ONSCREEN,false);
    }
    whiteboard_manager_->on_init_side();
}
예제 #6
0
void play_controller::enter_textbox()
{
    if(menu_handler_.get_textbox().active() == false) {
        return;
    }

    const std::string str = menu_handler_.get_textbox().box()->text();
    const unsigned int team_num = current_side();
    events::mouse_handler& mousehandler = mouse_handler_;

    switch(menu_handler_.get_textbox().mode()) {
    case gui::TEXTBOX_SEARCH:
        menu_handler_.do_search(str);
        menu_handler_.get_textbox().close(*gui_);
        break;
    case gui::TEXTBOX_MESSAGE:
        menu_handler_.do_speak();
        menu_handler_.get_textbox().close(*gui_);  //need to close that one after executing do_speak() !
        break;
    case gui::TEXTBOX_COMMAND:
        menu_handler_.get_textbox().close(*gui_);
        menu_handler_.do_command(str);
        break;
    case gui::TEXTBOX_AI:
        menu_handler_.get_textbox().close(*gui_);
        menu_handler_.do_ai_formula(str, team_num, mousehandler);
        break;
    default:
        menu_handler_.get_textbox().close(*gui_);
        ERR_DP << "unknown textbox mode" << std::endl;
    }
}
예제 #7
0
void playsingle_controller::end_turn(){
	if (linger_)
		end_turn_ = END_TURN_REQUIRED;
	else if (!is_browsing() && menu_handler_.end_turn(current_side())){
		end_turn_ = END_TURN_REQUIRED;
	}
}
예제 #8
0
void play_controller::play_side()
{
    //check for team-specific items in the scenario
    gui_->parse_team_overlays();
    do {
        update_viewing_player();
        {
            save_blocker blocker;
            maybe_do_init_side();
            if(is_regular_game_end()) {
                return;
            }
        }
        // This flag can be set by derived classes (in overridden functions).
        player_type_changed_ = false;

        statistics::reset_turn_stats(gamestate().board_.teams()[current_side() - 1].save_id());

        play_side_impl();

        if(is_regular_game_end()) {
            return;
        }

    } while (player_type_changed_);
    // Keep looping if the type of a team (human/ai/networked)
    // has changed mid-turn
    sync_end_turn();
}
예제 #9
0
void play_controller::process_keyup_event(const SDL_Event& event)
{
    // If the user has pressed 1 through 9, we want to show
    // how far the unit can move in that many turns
    if(event.key.keysym.sym >= '1' && event.key.keysym.sym <= '9') {
        const int new_path_turns = (event.type == SDL_KEYDOWN) ?
                                   event.key.keysym.sym - '1' : 0;

        if(new_path_turns != mouse_handler_.get_path_turns()) {
            mouse_handler_.set_path_turns(new_path_turns);

            const unit_map::iterator u = mouse_handler_.selected_unit();

            if(u.valid()) {
                // if it's not the unit's turn, we reset its moves
                unit_movement_resetter move_reset(*u, u->side() != current_side());

                mouse_handler_.set_current_paths(pathfind::paths(*u, false,
                                                 true, gamestate().board_.teams_[gui_->viewing_team()],
                                                 mouse_handler_.get_path_turns()));

                gui_->highlight_reach(mouse_handler_.current_paths());
            } else {
                mouse_handler_.select_hex(mouse_handler_.get_selected_hex(), false, false, false);
            }

        }
    } else if (event.key.keysym.sym == SDLK_TAB) {
        static CKey keys;
        if (!keys[SDLK_TAB]) {
            whiteboard_manager_->set_invert_behavior(false);
        }
    }
}
예제 #10
0
void playsingle_controller::show_turn_dialog(){
	if(preferences::turn_dialog() && !is_regular_game_end() ) {
		blindfold b(*gui_, true); //apply a blindfold for the duration of this dialog
		gui_->redraw_everything();
		gui_->recalculate_minimap();
		std::string message = _("It is now $name|’s turn");
		utils::string_map symbols;
		symbols["name"] = gamestate().board_.teams()[current_side() - 1].side_name();
		message = utils::interpolate_variables_into_string(message, &symbols);
		gui2::show_transient_message(gui_->video(), "", message);
	}
}
예제 #11
0
void playsingle_controller::execute_gotos()
{
	if(should_return_to_play_side())
	{
		return;
	}
	try
	{
		menu_handler_.execute_gotos(mouse_handler_, current_side());
	}
	catch (const return_to_play_side_exception&)
	{
	}
}
예제 #12
0
void playsingle_controller::play_ai_turn()
{
	LOG_NG << "is ai...\n";

	end_turn_enable(false);
	gui_->recalculate_minimap();

	const cursor::setter cursor_setter(cursor::WAIT);

	// Correct an oddball case where a human could have left delayed shroud
	// updates on before giving control to the AI. (The AI does not bother
	// with the undo stack, so it cannot delay shroud updates.)
	team & cur_team = current_team();
	if ( !cur_team.auto_shroud_updates() ) {
		// We just took control, so the undo stack is empty. We still need
		// to record this change for the replay though.
		synced_context::run_and_store("auto_shroud", replay_helper::get_auto_shroud(true));
	}
	undo_stack().clear();

	turn_data_.send_data();
	try {
		try {
			if (!should_return_to_play_side()) {
				ai::manager::play_turn(current_side());
			}
		}
		catch (return_to_play_side_exception&) {
		}
		catch (fallback_ai_to_human_exception&) {
			current_team().make_human();
			player_type_changed_ = true;
		}
	}
	catch(...) {
		turn_data_.sync_network();
		throw;
	}
	if(!should_return_to_play_side()) {
		end_turn_ = END_TURN_REQUIRED;
	}
	turn_data_.sync_network();
	gui_->recalculate_minimap();
	gui_->invalidate_unit();
	gui_->invalidate_game_status();
	gui_->invalidate_all();
	gui_->draw();
}
예제 #13
0
void playsingle_controller::play_side_impl()
{
	if (!skip_next_turn_) {
		end_turn_ = END_TURN_NONE;
	}
	if(replay_.get() != NULL) {
		REPLAY_RETURN res = replay_->play_side_impl();
		if(res == REPLAY_FOUND_END_TURN) {
			end_turn_ = END_TURN_SYNCED;
		}
		if (player_type_changed_) {
			replay_.reset();
		}
	} else if((current_team().is_local_human() && current_team().is_proxy_human())) {
		LOG_NG << "is human...\n";
		// 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(current_side()) == 0 && !(gamestate().board_.units().size() == 0 && current_side() == 1)) {
			end_turn_ = END_TURN_REQUIRED;
		}

		before_human_turn();
		if (end_turn_ == END_TURN_NONE) {
			play_human_turn();
		}
		if ( !player_type_changed_ && !is_regular_game_end()) {
			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())) {
		play_ai_turn();
	} else if(current_team().is_network()) {
		play_network_turn();
	} 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();
		}
	}
	else {
		// we should have skipped over empty controllers before so this shouldn't be possible
		ERR_NG << "Found invalid side controller " << current_team().controller().to_string() << " (" << current_team().proxy_controller().to_string() << ") for side " << current_team().side() << "\n";
	}
}
예제 #14
0
void playmp_controller::after_human_turn(){
	if(saved_game_.mp_settings().mp_countdown)
	{
		//time_left + turn_bonus + (action_bonus * number of actions done)
		const int new_time_in_secs = (current_team().countdown_time() / 1000)
			+ saved_game_.mp_settings().mp_countdown_turn_bonus
			+ saved_game_.mp_settings().mp_countdown_action_bonus * current_team().action_bonus_count();
		const int new_time = 1000 * std::min<int>(new_time_in_secs, saved_game_.mp_settings().mp_countdown_reservoir_time);

		current_team().set_action_bonus_count(0);
		current_team().set_countdown_time(new_time);
		resources::recorder->add_countdown_update(new_time, current_side());
	}
	LOG_NG << "playmp::after_human_turn...\n";

	// Normal post-processing for human turns (clear undos, end the turn, etc.)
	playsingle_controller::after_human_turn();
	//send one more time to make sure network is up-to-date.
	turn_data_.send_data();

}
예제 #15
0
파일: game.hpp 프로젝트: AI0867/wesnoth
	network::connection current_player() const
	{ return (nsides_ ? sides_[current_side()] : 0); }
예제 #16
0
void play_controller::do_init_side()
{
    set_scontext_synced sync;
    log_scope("player turn");
    // In case we might end up calling sync:network during the side turn events,
    // and we don't want do_init_side to be called when a player drops.
    gamestate_->init_side_done() = true;
    init_side_done_now_ = true;

    const std::string turn_num = std::to_string(turn());
    const std::string side_num = std::to_string(current_side());

    gamestate().gamedata_.get_variable("side_number") = current_side();

    // We might have skipped some sides because they were empty so it is not enough to check for side_num==1
    if(!gamestate().tod_manager_.has_turn_event_fired())
    {
        pump().fire("turn_" + turn_num);
        pump().fire("new_turn");
        gamestate().tod_manager_.turn_event_fired();
    }

    pump().fire("side_turn");
    pump().fire("side_" + side_num + "_turn");
    pump().fire("side_turn_" + turn_num);
    pump().fire("side_" + side_num + "_turn_" + turn_num);

    // We want to work out if units for this player should get healed,
    // and the player should get income now.
    // Healing/income happen if it's not the first turn of processing,
    // or if we are loading a game.
    if (turn() > 1) {
        gamestate().board_.new_turn(current_side());
        current_team().new_turn();

        // If the expense is less than the number of villages owned
        // times the village support capacity,
        // then we don't have to pay anything at all
        int expense = gamestate().board_.side_upkeep(current_side()) -
                      current_team().support();
        if(expense > 0) {
            current_team().spend_gold(expense);
        }

        calculate_healing(current_side(), !is_skipping_replay());
    }

    // Prepare the undo stack.
    undo_stack().new_side_turn(current_side());

    pump().fire("turn_refresh");
    pump().fire("side_" + side_num + "_turn_refresh");
    pump().fire("turn_" + turn_num + "_refresh");
    pump().fire("side_" + side_num + "_turn_" + turn_num + "_refresh");

    // Make sure vision is accurate.
    actions::clear_shroud(current_side(), true);
    init_side_end();
    check_victory();
    sync.do_final_checkup();
}
예제 #17
0
const team& play_controller::current_team() const
{
    assert(current_side() > 0 && current_side() <= int(gamestate().board_.teams().size()));
    return gamestate().board_.teams()[current_side() - 1];
}