Skip to content

Commit

Permalink
more refactor of play_side and game_end_exception.hpp
Browse files Browse the repository at this point in the history
Instead of having different exceptions (ai_end_turn_exception,
end_level_exception and restart_turn_exception) we now have one exception
(return_to_play_side_exception) that is used to escape from play_ai_turn
or play_slice and is catched in the play_side related functions.
The information why we returned to play_side is already stored in the
playsingle_controller object. That is also why we do not need the
possible_end_play_signal return value anymore.

play_controller::check_victory does not throw exceptions anymore
Also do_replay and thus turn_info::process_network_data don't throw
exceptions anymore when the scenario is finished by victory or defeat.
Instead it returns REPLAY_FOUND_END_LEVEL, this means
return_to_play_side_exception is not thrown during replay at all.

this also fixed up a previous commit 'refactor play_side' where
accidently play_idle_loop was called instead of play_human_turn in
play_side.
  • Loading branch information
gfgtdf committed Mar 3, 2015
1 parent 62cea30 commit fb68590
Show file tree
Hide file tree
Showing 30 changed files with 372 additions and 487 deletions.
21 changes: 2 additions & 19 deletions src/actions/attack.cpp
Expand Up @@ -1497,25 +1497,8 @@ static void advance_unit_at(const map_location& loc, const ai::unit_advancements
void attack_unit_and_advance(const map_location &attacker, const map_location &defender,
int attack_with, int defend_with, bool update_display,
const ai::unit_advancements_aspect& ai_advancement)
{ try
{
attack_unit(attacker, defender, attack_with, defend_with, update_display);
}
catch(end_level_exception&)
{

unit_map::const_iterator atku = resources::units->find(attacker);

if (atku != resources::units->end()) {
advance_unit_at(attacker, ai_advancement);
}

unit_map::const_iterator defu = resources::units->find(defender);
if (defu != resources::units->end()) {
advance_unit_at(defender, ai_advancement);
}
throw;
}
{
attack_unit(attacker, defender, attack_with, defend_with, update_display);
unit_map::const_iterator atku = resources::units->find(attacker);
if (atku != resources::units->end()) {
advance_unit_at(attacker, ai_advancement);
Expand Down
1 change: 1 addition & 0 deletions src/actions/move.cpp
Expand Up @@ -1270,6 +1270,7 @@ size_t move_unit_and_record(const std::vector<map_location> &steps,
set_scontext_synced sync;
size_t r = move_unit_internal(undo_stack, show_move, interrupted, mover);
resources::controller->check_victory();
resources::controller->maybe_throw_return_to_play_side();
sync.do_final_checkup();
return r;
}
Expand Down
12 changes: 2 additions & 10 deletions src/ai/actions.cpp
Expand Up @@ -94,23 +94,14 @@ void action_result::execute()
if (is_success()){
try {
do_execute();
} catch (end_level_exception&) {
} catch (return_to_play_side_exception&) {
if (!is_ok()) { DBG_AI_ACTIONS << "Return value of AI ACTION was not checked. This may cause bugs! " << std::endl; } //Demotes to DBG "unchecked result" warning
throw;
}
}
if (is_success()){
check_after();
}
if(resources::controller->is_end_turn()) {
throw ai_end_turn_exception();
}

if(playsingle_controller* psc = dynamic_cast<playsingle_controller*>(resources::controller)) {
if(psc->get_player_type_changed()) {
throw restart_turn_exception();
}
}
is_execution_ = false;
}

Expand Down Expand Up @@ -302,6 +293,7 @@ void attack_result::do_execute()
set_scontext_synced sync;
attack_unit_and_advance(attacker_loc_, defender_loc_, attacker_weapon, defender_weapon, true, advancements_);
resources::controller->check_victory();
resources::controller->maybe_throw_return_to_play_side();
sync.do_final_checkup();
}
else
Expand Down
18 changes: 6 additions & 12 deletions src/ai/manager.cpp
Expand Up @@ -788,18 +788,12 @@ void manager::play_turn( side_number side ){
num_interact_ = 0;
const int turn_start_time = SDL_GetTicks();
/*hack. @todo 1.9 rework via extended event system*/
try {
get_ai_info().recent_attacks.clear();
interface& ai_obj = get_active_ai_for_side(side);
resources::game_events->pump().fire("ai turn");
raise_turn_started();
ai_obj.new_turn();
ai_obj.play_turn();
}
catch (const ai_end_turn_exception&) {
}
catch(const restart_turn_exception&) {
}
get_ai_info().recent_attacks.clear();
interface& ai_obj = get_active_ai_for_side(side);
resources::game_events->pump().fire("ai turn");
raise_turn_started();
ai_obj.new_turn();
ai_obj.play_turn();
const int turn_end_time= SDL_GetTicks();
DBG_AI_MANAGER << "side " << side << ": number of user interactions: "<<num_interact_<<std::endl;
DBG_AI_MANAGER << "side " << side << ": total turn time: "<<turn_end_time - turn_start_time << " ms "<< std::endl;
Expand Down
2 changes: 1 addition & 1 deletion src/dialogs.cpp
Expand Up @@ -162,7 +162,7 @@ gui::dialog_button_action::RESULT delete_recall_unit::button_pressed(int menu_se
assert(dismissed_unit);

// Record the dismissal, then delete the unit.
synced_context::run_in_synced_context("disband", replay_helper::get_disband(dismissed_unit->id()));
synced_context::run_and_throw("disband", replay_helper::get_disband(dismissed_unit->id()));
//recorder.add_disband(dismissed_unit->id());
//recall_list.erase(dismissed_unit);

Expand Down
106 changes: 6 additions & 100 deletions src/game_end_exceptions.hpp
Expand Up @@ -40,74 +40,22 @@ MAKE_ENUM(LEVEL_RESULT,
MAKE_ENUM_STREAM_OPS1(LEVEL_RESULT)

/**
* Exception used to escape form the ai code in case of [end_turn].
* Exception used to escape form the ai or ui code to playsingle_controller::play_side.
* Never thrown during replays.
*/
class ai_end_turn_exception
: public tlua_jailbreak_exception, public std::exception
class return_to_play_side_exception : public tlua_jailbreak_exception, public std::exception
{
public:

ai_end_turn_exception()
return_to_play_side_exception()
: tlua_jailbreak_exception()
, std::exception()
{
}
const char * what() const throw() { return "ai_end_turn_exception"; }
const char * what() const throw() { return "return_to_play_side_exception"; }
private:

IMPLEMENT_LUA_JAILBREAK_EXCEPTION(ai_end_turn_exception)
};

/**
* Exception used to signal the end of a player turn.
*/
class restart_turn_exception
: public tlua_jailbreak_exception, public std::exception
{
public:

restart_turn_exception()
: tlua_jailbreak_exception()
, std::exception()
{
}
const char * what() const throw() { return "restart_turn_exception"; }

private:

IMPLEMENT_LUA_JAILBREAK_EXCEPTION(restart_turn_exception)
};

/**
* Struct used to transmit info caught from an end_turn_exception.
*/
struct end_level_struct
{
};

/**
* Exception used to signal the end of a scenario.
*/
class end_level_exception
: public tlua_jailbreak_exception
, public std::exception
{
public:

end_level_exception()
: tlua_jailbreak_exception()
, std::exception()
{
}

end_level_struct to_struct() {
return end_level_struct();
}

const char * what() const throw() { return "end_level_exception"; }
private:

IMPLEMENT_LUA_JAILBREAK_EXCEPTION(end_level_exception)
IMPLEMENT_LUA_JAILBREAK_EXCEPTION(return_to_play_side_exception)
};

class quit_game_exception
Expand All @@ -125,48 +73,6 @@ class quit_game_exception
private:
IMPLEMENT_LUA_JAILBREAK_EXCEPTION(quit_game_exception)
};
/**
* The two end_*_exceptions are caught and transformed to this signaling object
*/
typedef boost::optional<end_level_struct> possible_end_play_signal;

#define HANDLE_END_PLAY_SIGNAL( X )\
do\
{\
try {\
X;\
} catch (end_level_exception & e) {\
return possible_end_play_signal(e.to_struct());\
}\
}\
while(0)



#define PROPOGATE_END_PLAY_SIGNAL( X )\
do\
{\
possible_end_play_signal temp;\
temp = X;\
if (temp) {\
return temp;\
}\
}\
while(0)



#define HANDLE_AND_PROPOGATE_END_PLAY_SIGNAL( X )\
do\
{\
possible_end_play_signal temp;\
HANDLE_END_PLAY_SIGNAL( temp = X );\
if (temp) {\
return temp;\
}\
}\
while(0)


/**
* The non-persistent part of end_level_data
Expand Down
2 changes: 1 addition & 1 deletion src/game_events/menu_item.cpp
Expand Up @@ -208,7 +208,7 @@ void wml_menu_item::fire_event(const map_location & event_hex, const game_data &
// note that there coudn't be a user choice during the last "select" event because it didn't run in a synced context.
if ( needs_select_ && last_select.valid() )
{
synced_context::run_in_synced_context("fire_event", replay_helper::get_event(event_name_, event_hex, &last_select));
synced_context::run_and_throw("fire_event", replay_helper::get_event(event_name_, event_hex, &last_select));
}
else
{
Expand Down
16 changes: 4 additions & 12 deletions src/game_initialization/playcampaign.cpp
Expand Up @@ -153,7 +153,7 @@ LEVEL_RESULT play_replay(display& disp, saved_game& gamestate, const config& gam
gui2::show_error_message(disp.video(), _("The game could not be loaded: ") + e.message);
}

} catch(quit_game_exception& e) {
} catch(quit_game_exception&) {
LOG_NG << "The replay was aborted\n";
return QUIT;
} catch(game::game_error& e) {
Expand Down Expand Up @@ -207,11 +207,7 @@ static LEVEL_RESULT playsingle_scenario(const config& game_config,
show_carryover_message(state_of_game, playcontroller, disp, end_level, res);
if(!disp.video().faked())
{
try {
playcontroller.maybe_linger();
} catch(end_level_exception&) {
return QUIT;
}
playcontroller.maybe_linger();
}
state_of_game.set_snapshot(playcontroller.to_config());
return res;
Expand Down Expand Up @@ -249,11 +245,7 @@ static LEVEL_RESULT playmp_scenario(const config& game_config,
}
if(!disp.video().faked())
{
try {
playcontroller.maybe_linger();
} catch(end_level_exception&) {
return QUIT;
}
playcontroller.maybe_linger();
}
playcontroller.update_savegame_snapshot();
return res;
Expand Down Expand Up @@ -300,7 +292,7 @@ LEVEL_RESULT play_game(game_display& disp, saved_game& gamestate,
} catch(game::load_game_failed& e) {
gui2::show_error_message(disp.video(), _("The game could not be loaded: ") + e.message);
return QUIT;
} catch(quit_game_exception& e) {
} catch(quit_game_exception&) {
LOG_NG << "The game was aborted\n";
return QUIT;
} catch(game::game_error& e) {
Expand Down
8 changes: 4 additions & 4 deletions src/hotkey/command_executor.hpp
Expand Up @@ -79,12 +79,12 @@ class command_executor
virtual void ai_formula() {}
virtual void clear_messages() {}
virtual void change_language() {}
virtual possible_end_play_signal play_replay() { return boost::none; }
virtual void play_replay() { }
virtual void reset_replay() {}
virtual void stop_replay() {}
virtual possible_end_play_signal replay_next_turn() { return boost::none; }
virtual possible_end_play_signal replay_next_side() { return boost::none; }
virtual possible_end_play_signal replay_next_move() { return boost::none; }
virtual void replay_next_turn() { }
virtual void replay_next_side() { }
virtual void replay_next_move() { }
virtual void replay_show_everything() {}
virtual void replay_show_each() {}
virtual void replay_show_team1() {}
Expand Down
8 changes: 4 additions & 4 deletions src/hotkey_handler_replay.hpp
Expand Up @@ -42,13 +42,13 @@ class replay_controller::hotkey_handler : public play_controller::hotkey_handler
{ return replay_controller_.reset_replay(); }
virtual void stop_replay() OVERRIDE
{ return replay_controller_.stop_replay(); }
virtual possible_end_play_signal play_replay() OVERRIDE
virtual void play_replay() OVERRIDE
{ return replay_controller_.play_replay(); }
virtual possible_end_play_signal replay_next_turn() OVERRIDE
virtual void replay_next_turn() OVERRIDE
{ return replay_controller_.replay_next_turn(); }
virtual possible_end_play_signal replay_next_side() OVERRIDE
virtual void replay_next_side() OVERRIDE
{ return replay_controller_.replay_next_side(); }
virtual possible_end_play_signal replay_next_move() OVERRIDE
virtual void replay_next_move() OVERRIDE
{ return replay_controller_.replay_next_move(); }
virtual void replay_show_everything() OVERRIDE
{ return replay_controller_.replay_show_everything(); }
Expand Down
13 changes: 6 additions & 7 deletions src/menu_events.cpp
Expand Up @@ -663,7 +663,7 @@ bool menu_handler::do_recruit(const std::string &name, int side_num,

// Do the recruiting.

synced_context::run_in_synced_context("recruit", replay_helper::get_recruit(u_type->id(), loc, recruited_from));
synced_context::run_and_throw("recruit", replay_helper::get_recruit(u_type->id(), loc, recruited_from));
return true;
}
return false;
Expand Down Expand Up @@ -749,11 +749,10 @@ void menu_handler::recall(int side_num, const map_location &last_hex)
}

if (!pc_.get_whiteboard() || !pc_.get_whiteboard()->save_recall(*recall_list_team->at(res), side_num, recall_location)) {
bool success = synced_context::run_in_synced_context("recall",
bool success = synced_context::run_and_throw("recall",
replay_helper::get_recall(recall_list_team->at(res)->id(), recall_location, recall_from),
true,
true,
true,
synced_context::ignore_error_function);

if(!success)
Expand Down Expand Up @@ -795,12 +794,12 @@ void menu_handler::toggle_shroud_updates(int side_num)
if (!auto_shroud) update_shroud_now(side_num);

// Toggle the setting and record this.
synced_context::run_in_synced_context("auto_shroud", replay_helper::get_auto_shroud(!auto_shroud));
synced_context::run_and_throw("auto_shroud", replay_helper::get_auto_shroud(!auto_shroud));
}

void menu_handler::update_shroud_now(int /* side_num */)
{
synced_context::run_in_synced_context("update_shroud", replay_helper::get_update_shroud());
synced_context::run_and_throw("update_shroud", replay_helper::get_update_shroud());
}


Expand Down Expand Up @@ -2971,7 +2970,7 @@ void console_handler::do_next_level()
e.proceed_to_next_level = true;
e.is_victory = true;
menu_handler_.pc_.set_end_level_data(e);
throw end_level_exception();
throw return_to_play_side_exception();
}

void console_handler::do_choose_level() {
Expand Down Expand Up @@ -3021,7 +3020,7 @@ void console_handler::do_choose_level() {
e.proceed_to_next_level = true;
e.is_victory = true;
menu_handler_.pc_.set_end_level_data(e);
throw end_level_exception();
throw return_to_play_side_exception();
}
}

Expand Down
2 changes: 1 addition & 1 deletion src/mouse_events.cpp
Expand Up @@ -1156,7 +1156,7 @@ void mouse_handler::attack_enemy_(const map_location& att_loc

const tod_manager & tod_man = pc_.get_tod_manager_const();

synced_context::run_in_synced_context("attack", replay_helper::get_attack(attacker_loc, defender_loc, att.attack_num, def.attack_num,
synced_context::run_and_throw("attack", replay_helper::get_attack(attacker_loc, defender_loc, att.attack_num, def.attack_num,
attacker->type_id(), defender->type_id(), att.level,
def.level, tod_man.turn(), tod_man.get_time_of_day()));
}
Expand Down

0 comments on commit fb68590

Please sign in to comment.