00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019 #include "playsingle_controller.hpp"
00020
00021 #include "construct_dialog.hpp"
00022 #include "ai_interface.hpp"
00023 #include "game_errors.hpp"
00024 #include "gettext.hpp"
00025 #include "intro.hpp"
00026 #include "log.hpp"
00027 #include "marked-up_text.hpp"
00028 #include "playturn.hpp"
00029 #include "sound.hpp"
00030 #include "upload_log.hpp"
00031
00032 #define ERR_NG LOG_STREAM(err, engine)
00033 #define LOG_NG LOG_STREAM(info, engine)
00034
00035 playsingle_controller::playsingle_controller(const config& level, game_state& state_of_game,
00036 const int ticks, const int num_turns, const config& game_config, CVideo& video,
00037 bool skip_replay)
00038 : play_controller(level, state_of_game, ticks, num_turns, game_config, video, skip_replay, false),
00039 cursor_setter(cursor::NORMAL), replay_sender_(recorder) , turn_over_(false)
00040 {
00041 end_turn_ = false;
00042 replaying_ = false;
00043
00044
00045 if (state_of_game.completion == "victory" || state_of_game.completion == "defeat")
00046 {
00047 std::cerr << "Setting linger mode.\n";
00048 browse_ = linger_ = true;
00049 }
00050 }
00051
00052 void playsingle_controller::init_gui(){
00053 LOG_NG << "Initializing GUI... " << (SDL_GetTicks() - ticks_) << "\n";
00054 play_controller::init_gui();
00055
00056 if(first_human_team_ != -1) {
00057 gui_->scroll_to_tile(map_.starting_position(first_human_team_ + 1), game_display::WARP);
00058 }
00059 gui_->scroll_to_tile(map_.starting_position(1), game_display::WARP);
00060
00061 update_locker lock_display(gui_->video(),recorder.is_skipping());
00062 events::raise_draw_event();
00063 gui_->draw();
00064 for(std::vector<team>::iterator t = teams_.begin(); t != teams_.end(); ++t) {
00065 ::clear_shroud(*gui_,map_,units_,teams_,(t-teams_.begin()));
00066 }
00067 }
00068
00069 void playsingle_controller::recruit(){
00070 if (!browse_)
00071 menu_handler_.recruit(browse_, player_number_, mouse_handler_.get_last_hex());
00072 }
00073
00074 void playsingle_controller::repeat_recruit(){
00075 if (!browse_)
00076 menu_handler_.repeat_recruit(player_number_, mouse_handler_.get_last_hex());
00077 }
00078
00079 void playsingle_controller::recall(){
00080 if (!browse_)
00081 menu_handler_.recall(player_number_, mouse_handler_.get_last_hex());
00082 }
00083
00084 void playsingle_controller::toggle_shroud_updates(){
00085 menu_handler_.toggle_shroud_updates(player_number_);
00086 }
00087
00088 void playsingle_controller::update_shroud_now(){
00089 menu_handler_.update_shroud_now(player_number_);
00090 }
00091
00092 void playsingle_controller::end_turn(){
00093 if (linger_)
00094 end_turn_ = true;
00095 else if (!browse_){
00096 end_turn_ = menu_handler_.end_turn(player_number_);
00097 }
00098 }
00099
00100 void playsingle_controller::rename_unit(){
00101 menu_handler_.rename_unit(mouse_handler_);
00102 }
00103
00104 void playsingle_controller::create_unit(){
00105 menu_handler_.create_unit(mouse_handler_);
00106 }
00107
00108 void playsingle_controller::change_unit_side(){
00109 menu_handler_.change_unit_side(mouse_handler_);
00110 }
00111
00112 void playsingle_controller::label_terrain(bool team_only){
00113 menu_handler_.label_terrain(mouse_handler_, team_only);
00114 }
00115
00116 void playsingle_controller::continue_move(){
00117 menu_handler_.continue_move(mouse_handler_, player_number_);
00118 }
00119
00120 void playsingle_controller::unit_hold_position(){
00121 if (!browse_)
00122 menu_handler_.unit_hold_position(mouse_handler_, player_number_);
00123 }
00124
00125 void playsingle_controller::end_unit_turn(){
00126 if (!browse_)
00127 menu_handler_.end_unit_turn(mouse_handler_, player_number_);
00128 }
00129
00130 void playsingle_controller::user_command(){
00131 menu_handler_.user_command();
00132 }
00133
00134 void playsingle_controller::custom_command(){
00135 menu_handler_.custom_command(mouse_handler_, player_number_);
00136 }
00137
00138 void playsingle_controller::ai_formula(){
00139 menu_handler_.ai_formula();
00140 }
00141
00142 void playsingle_controller::clear_messages(){
00143 menu_handler_.clear_messages();
00144 }
00145
00146 #ifdef USRCMD2
00147 void playsingle_controller::user_command_2(){
00148 menu_handler_.user_command_2();
00149 }
00150
00151 void playsingle_controller::user_command_3(){
00152 menu_handler_.user_command_3();
00153 }
00154 #endif
00155
00156 void playsingle_controller::report_victory(
00157 std::stringstream& report,
00158 end_level_exception& end_level,
00159 int player_gold,
00160 int remaining_gold, int finishing_bonus_per_turn,
00161 int turns_left, int finishing_bonus)
00162 {
00163 report << _("Remaining gold: ")
00164 << remaining_gold << "\n";
00165 if(end_level.gold_bonus) {
00166 report << _("Early finish bonus: ")
00167 << finishing_bonus_per_turn
00168 << " " << _("per turn") << "\n"
00169 << font::BOLD_TEXT << _("Turns finished early: ")
00170 << turns_left << "\n"
00171 << _("Bonus: ")
00172 << finishing_bonus << "\n"
00173 << _("Gold: ")
00174 << (remaining_gold + finishing_bonus);
00175 }
00176 report << '\n' << _("Carry over percentage: ") << end_level.carryover_percentage;
00177 if(end_level.carryover_add) {
00178 report << '\n' << font::BOLD_TEXT << _("Bonus Gold: ") << player_gold;
00179 } else {
00180 report << '\n' << font::BOLD_TEXT << _("Retained Gold: ") << player_gold;
00181 }
00182
00183 std::string goldmsg;
00184 utils::string_map symbols;
00185 symbols["gold"] = lexical_cast_default<std::string>(player_gold);
00186
00187
00188 if(end_level.carryover_add) {
00189 goldmsg = vngettext(
00190 "You will start the next scenario with $gold "
00191 "on top of the defined minimum starting gold.",
00192 "You will start the next scenario with $gold "
00193 "on top of the defined minimum starting gold.",
00194 player_gold, symbols);
00195
00196 } else {
00197 goldmsg = vngettext(
00198 "You will start the next scenario with $gold "
00199 "or its defined minimum starting gold, "
00200 "whichever is higher.",
00201 "You will start the next scenario with $gold "
00202 "or its defined minimum starting gold, "
00203 "whichever is higher.",
00204 player_gold, symbols);
00205 }
00206
00207
00208 report << '\n' << goldmsg;
00209 }
00210
00211 LEVEL_RESULT playsingle_controller::play_scenario(const std::vector<config*>& story, upload_log& log,
00212 bool skip_replay)
00213 {
00214 LOG_NG << "in playsingle_controller::play_scenario()...\n";
00215
00216
00217 const config::child_list& m = level_.get_children("music");
00218 config::const_child_iterator i;
00219 for (i = m.begin(); i != m.end(); i++) {
00220 sound::play_music_config(**i);
00221 }
00222 sound::commit_music_changes();
00223
00224 if(!skip_replay) {
00225 for(std::vector<config*>::const_iterator story_i = story.begin(); story_i != story.end(); ++story_i) {
00226
00227 show_intro(*gui_,**story_i, level_);
00228 }
00229 }
00230 gui_->labels().read(level_, game_events::get_state_of_game());
00231
00232
00233 const config::child_list& overlays = level_.get_children("item");
00234 for(config::child_list::const_iterator overlay = overlays.begin(); overlay != overlays.end(); ++overlay) {
00235 gui_->add_overlay(gamemap::location(**overlay,game_events::get_state_of_game()),(**overlay)["image"], (**overlay)["halo"]);
00236 }
00237
00238 victory_conditions::set_victory_when_enemies_defeated(
00239 level_["victory_when_enemies_defeated"] != "no");
00240 victory_conditions::set_carryover_percentage(
00241 lexical_cast_default<int>(level_["carryover_percentage"],
00242 game_config::gold_carryover_percentage));
00243 victory_conditions::set_carryover_add(utils::string_bool(
00244 level_["carryover_add"], game_config::gold_carryover_add));
00245
00246 LOG_NG << "entering try... " << (SDL_GetTicks() - ticks_) << "\n";
00247 try {
00248
00249 if (first_human_team_ != -1) {
00250 log.start(gamestate_, teams_[first_human_team_], first_human_team_ + 1, units_,
00251 loading_game_ ? gamestate_.get_variable("turn_number") : "", status_.number_of_turns());
00252 }
00253
00254 fire_prestart(!loading_game_);
00255 init_gui();
00256
00257 LOG_NG << "first_time..." << (recorder.is_skipping() ? "skipping" : "no skip") << "\n";
00258
00259 fire_start(!loading_game_);
00260 gui_->recalculate_minimap();
00261
00262 replaying_ = (recorder.at_end() == false);
00263
00264 LOG_NG << "starting main loop\n" << (SDL_GetTicks() - ticks_) << "\n";
00265
00266
00267 std::vector<team>::iterator t;
00268 for(t = teams_.begin(); t != teams_.end(); ++t) {
00269 std::string countd_enabled = level_["mp_countdown"].c_str();
00270 if (utils::string_bool(countd_enabled) && !loading_game_ ){
00271 t->set_countdown_time(1000 * lexical_cast_default<int>(level_["mp_countdown_init_time"],0));
00272 }
00273 }
00274
00275
00276 if (linger_)
00277 throw end_level_exception(SKIP_TO_LINGER);
00278
00279
00280
00281 bool save = !loading_game_;
00282 for(; ; first_player_ = 1) {
00283 play_turn(save);
00284 save = true;
00285 }
00286
00287 } catch(game::load_game_exception&) {
00288
00289 log.quit(status_.turn());
00290 throw;
00291 } catch(end_level_exception& end_level) {
00292 bool obs = team_manager_.is_observer();
00293 if (game_config::exit_at_end) {
00294 exit(0);
00295 }
00296 if (end_level.result == DEFEAT || end_level.result == VICTORY) {
00297 gamestate_.completion = (end_level.result == VICTORY) ? "victory" : "defeat";
00298 recorder.set_save_info_completion(gamestate_.completion);
00299
00300
00301 if (!obs) {
00302 config cfg;
00303 config& info = cfg.add_child("info");
00304 info["type"] = "termination";
00305 info["condition"] = "game over";
00306 info["result"] = gamestate_.completion;
00307 network::send_data(cfg, 0, true);
00308 } else {
00309 gui::message_dialog(*gui_,_("Game Over"),
00310 _("The game is over.")).show();
00311 return OBSERVER_END;
00312 }
00313 }
00314
00315 if(end_level.result == QUIT) {
00316 log.quit(status_.turn());
00317 return end_level.result;
00318 } else if(end_level.result == DEFEAT) {
00319 gamestate_.completion = "defeat";
00320 log.defeat(status_.turn());
00321 try {
00322 game_events::fire("defeat");
00323 } catch(end_level_exception&) {
00324 }
00325
00326 if (!obs)
00327 return DEFEAT;
00328 else
00329 return QUIT;
00330 } else if (end_level.result == VICTORY
00331 || end_level.result == LEVEL_CONTINUE
00332 || end_level.result == LEVEL_CONTINUE_NO_SAVE) {
00333 if(end_level.result == LEVEL_CONTINUE_NO_SAVE) {
00334 gamestate_.completion = "running";
00335 } else {
00336 gamestate_.completion = "victory";
00337 }
00338 recorder.set_save_info_completion(gamestate_.completion);
00339 try {
00340 game_events::fire("victory");
00341 } catch(end_level_exception&) {
00342 }
00343 if (first_human_team_ != -1)
00344 log.victory(status_.turn(), teams_[first_human_team_].gold());
00345
00346 const bool has_next_scenario = !gamestate_.next_scenario.empty() &&
00347 gamestate_.next_scenario != "null";
00348
00349
00350 std::vector<team>::iterator i;
00351 for (i = teams_.begin(); i != teams_.end(); ++i) {
00352 player_info *player=gamestate_.get_player(i->save_id());
00353 if (player)
00354 player->name = i->current_player();
00355 }
00356
00357
00358 for(unit_map::iterator un = units_.begin(); un != units_.end(); ++un) {
00359 player_info *player=gamestate_.get_player(teams_[un->second.side()-1].save_id());
00360
00361 if(player) {
00362 un->second.new_turn();
00363 un->second.new_level();
00364 player->available_units.push_back(un->second);
00365 }
00366 }
00367
00368
00369
00370 if(end_level.result == LEVEL_CONTINUE || end_level.result == LEVEL_CONTINUE_NO_SAVE) {
00371 for(i=teams_.begin(); i!=teams_.end(); ++i) {
00372 player_info *player=gamestate_.get_player(i->save_id());
00373 if(player) {
00374 player->gold = i->gold();
00375 }
00376 }
00377
00378 return end_level.result == LEVEL_CONTINUE_NO_SAVE ? LEVEL_CONTINUE_NO_SAVE : VICTORY;
00379 }
00380
00381 std::stringstream report;
00382 std::string title;
00383
00384 if (obs) {
00385 title = _("Scenario Report");
00386 } else {
00387 title = _("Victory");
00388 report << font::BOLD_TEXT << _("You have emerged victorious!") << "\n~\n";
00389 }
00390 if (gamestate_.players.size() > 0 &&
00391 (has_next_scenario ||
00392 gamestate_.campaign_type == "test")) {
00393 const int finishing_bonus_per_turn =
00394 map_.villages().size() * game_config::village_income +
00395 game_config::base_income;
00396 const int turns_left = maximum<int>(0,status_.number_of_turns() - status_.turn());
00397 const int finishing_bonus = end_level.gold_bonus ?
00398 (finishing_bonus_per_turn * turns_left) : 0;
00399
00400 for(i=teams_.begin(); i!=teams_.end(); ++i) {
00401 player_info *player=gamestate_.get_player(i->save_id());
00402
00403 if (player) {
00404
00405 player->gold = ((i->gold() + finishing_bonus)
00406 * end_level.carryover_percentage) / 100;
00407 player->gold_add = end_level.carryover_add;
00408
00409
00410 if (!i->is_persistent())
00411 continue;
00412
00413 if(gamestate_.players.size()>1) {
00414 if(i!=teams_.begin()) {
00415 report << "\n";
00416 }
00417
00418 report << font::BOLD_TEXT << i->current_player() << "\n";
00419 }
00420
00421 report_victory(report, end_level, player->gold, i->gold(), finishing_bonus_per_turn, turns_left, finishing_bonus);
00422 }
00423 }
00424 }
00425
00426 gui::message_dialog(*gui_, title, report.str()).show();
00427
00428 return VICTORY;
00429 } else if (end_level.result == SKIP_TO_LINGER) {
00430 LOG_NG << "resuming from loaded linger state...\n";
00431 return VICTORY;
00432 }
00433 }
00434 catch(replay::error&) {
00435 gui::message_dialog(*gui_,"",_("The file you have tried to load is corrupt")).show();
00436 return QUIT;
00437 }
00438 catch(network::error& e) {
00439 bool disconnect = false;
00440 if(e.socket) {
00441 e.disconnect();
00442 disconnect = true;
00443 }
00444
00445 menu_handler_.save_game(_("A network disconnection has occurred, and the game cannot continue. Do you want to save the game?"),gui::YES_NO);
00446 if(disconnect) {
00447 throw network::error();
00448 } else {
00449 return QUIT;
00450 }
00451 }
00452
00453 return QUIT;
00454 }
00455
00456 void playsingle_controller::play_turn(bool save)
00457 {
00458 gui_->new_turn();
00459 gui_->invalidate_game_status();
00460 events::raise_draw_event();
00461
00462 LOG_NG << "turn: " << status_.turn() << "\n";
00463
00464 if(non_interactive())
00465 std::cout << "Turn " << status_.turn() << ":" << std::endl;
00466
00467
00468 for(player_number_ = first_player_; player_number_ <= teams_.size(); player_number_++) {
00469
00470 if (current_team().is_empty()) continue;
00471
00472 init_side(player_number_ - 1);
00473
00474 if (replaying_) {
00475 LOG_NG << "doing replay " << player_number_ << "\n";
00476 try {
00477 replaying_ = ::do_replay(*gui_, map_, units_, teams_,
00478 player_number_, status_, gamestate_);
00479 } catch(replay::error&) {
00480 gui::message_dialog(*gui_,"",_("The file you have tried to load is corrupt")).show();
00481
00482 replaying_ = false;
00483 }
00484 LOG_NG << "result of replay: " << (replaying_?"true":"false") << "\n";
00485 } else {
00486
00487 if ((current_team().is_human() && team_units(units_, player_number_) == 0))
00488 {
00489 turn_info turn_data(gamestate_, status_, *gui_, map_,
00490 teams_, player_number_, units_, replay_sender_, undo_stack_);
00491 recorder.end_turn();
00492 turn_data.sync_network();
00493 continue;
00494 }
00495 play_side(player_number_, save);
00496 }
00497
00498 finish_side_turn();
00499
00500 if(non_interactive()) {
00501 std::cout << " Player " << player_number_ << ": " <<
00502 current_team().villages().size() << " Villages" <<
00503 std::endl;
00504 }
00505
00506 check_victory(units_, teams_, *gui_);
00507 }
00508
00509
00510 check_time_over();
00511
00512 finish_turn();
00513 }
00514
00515 void playsingle_controller::play_side(const unsigned int team_index, bool save)
00516 {
00517 do {
00518
00519
00520
00521 player_type_changed_ = false;
00522 end_turn_ = false;
00523
00524 statistics::reset_turn_stats(player_number_);
00525
00526 if(current_team().is_human()) {
00527 LOG_NG << "is human...\n";
00528 try{
00529 before_human_turn(save);
00530 play_human_turn();
00531 after_human_turn();
00532 } catch(end_turn_exception& end_turn) {
00533 if (end_turn.redo == team_index) {
00534 player_type_changed_ = true;
00535
00536
00537 if (!teams_[team_index-1].is_human()) {
00538 int t = find_human_team_before(team_index);
00539 if (t > 0) {
00540 gui_->set_team(t-1);
00541 gui_->recalculate_minimap();
00542 gui_->invalidate_all();
00543 gui_->draw(true,true);
00544 }
00545 }
00546 }
00547 }
00548
00549 if(game_config::debug)
00550 game_display::clear_debug_highlights();
00551
00552 LOG_NG << "human finished turn...\n";
00553 } else if(current_team().is_ai()) {
00554 play_ai_turn();
00555 }
00556 } while (player_type_changed_);
00557
00558
00559 }
00560
00561 void playsingle_controller::before_human_turn(bool save)
00562 {
00563 log_scope("player turn");
00564 browse_ = false;
00565 linger_ = false;
00566
00567 gui_->set_team(player_number_ - 1);
00568 gui_->recalculate_minimap();
00569 gui_->invalidate_all();
00570 gui_->draw(true,true);
00571
00572 if (save) {
00573 menu_handler_.autosave(gamestate_.label, status_.turn(), gamestate_.starting_pos);
00574 }
00575
00576 if(preferences::turn_bell()) {
00577 sound::play_bell(game_config::sounds::turn_bell);
00578 }
00579
00580 if(preferences::turn_dialog()) {
00581 std::string message = _("It is now $name|'s turn");
00582 utils::string_map symbols;
00583 symbols["name"] = teams_[player_number_ - 1].current_player();
00584 message = utils::interpolate_variables_into_string(message, &symbols);
00585 gui::message_dialog(*gui_, "", message).show();
00586 }
00587
00588
00589 std::vector<gamemap::location> gotos;
00590
00591 for(unit_map::iterator ui = units_.begin(); ui != units_.end(); ++ui) {
00592 if(ui->second.get_goto() == ui->first)
00593 ui->second.set_goto(gamemap::location());
00594
00595 if(ui->second.side() == player_number_ && map_.on_board(ui->second.get_goto()))
00596 gotos.push_back(ui->first);
00597 }
00598
00599 for(std::vector<gamemap::location>::const_iterator g = gotos.begin(); g != gotos.end(); ++g) {
00600 unit_map::const_iterator ui = units_.find(*g);
00601 menu_handler_.move_unit_to_loc(ui,ui->second.get_goto(),false, player_number_, mouse_handler_);
00602 }
00603
00604
00605 gui_->set_route(NULL);
00606 }
00607
00608 void playsingle_controller::play_human_turn(){
00609 gui_->enable_menu("endturn", true);
00610 while(!end_turn_) {
00611 play_slice();
00612 gui_->draw();
00613 }
00614 }
00615
00616 void playsingle_controller::linger(upload_log& log)
00617 {
00618 LOG_NG << "beginning end-of-scenario linger\n";
00619 browse_ = true;
00620 linger_ = true;
00621
00622
00623
00624 gui_->set_game_mode(game_display::LINGER_SP);
00625
00626
00627
00628
00629 gamestate_.completion = "running";
00630
00631
00632 gui_->get_theme().refresh_title2(std::string("button-endturn"), std::string("title2"));
00633 gui_->invalidate_theme();
00634 gui_->redraw_everything();
00635
00636
00637 for (unit_map::iterator u = units_.begin(); u != units_.end(); u++) {
00638 u->second.set_user_end_turn(true);
00639 }
00640 try {
00641
00642
00643 gui_->enable_menu("endturn", true);
00644 while(!end_turn_) {
00645
00646 player_number_ = first_player_;
00647 play_slice();
00648
00649 gui_->draw();
00650 }
00651 } catch(game::load_game_exception&) {
00652
00653 log.quit(status_.turn());
00654 throw;
00655 }
00656
00657
00658 gui_->get_theme().refresh_title2(std::string("button-endturn"), std::string("title"));
00659 gui_->invalidate_theme();
00660 gui_->redraw_everything();
00661 gui_->set_game_mode(game_display::RUNNING);
00662
00663 LOG_NG << "ending end-of-scenario linger\n";
00664 }
00665
00666 void playsingle_controller::end_turn_record()
00667 {
00668 if (!turn_over_)
00669 {
00670 turn_over_ = true;
00671 recorder.end_turn();
00672 }
00673 }
00674 void playsingle_controller::end_turn_record_unlock()
00675 {
00676 turn_over_ = false;
00677 }
00678
00679 void playsingle_controller::after_human_turn(){
00680 end_turn_record();
00681 end_turn_record_unlock();
00682 menu_handler_.clear_undo_stack(player_number_);
00683
00684 if(teams_[player_number_-1].uses_fog()) {
00685
00686 recalculate_fog(map_,units_,teams_,player_number_-1);
00687 }
00688
00689 gui_->set_route(NULL);
00690 gui_->unhighlight_reach();
00691 }
00692
00693 void playsingle_controller::play_ai_turn(){
00694 LOG_NG << "is ai...\n";
00695 gui_->enable_menu("endturn", false);
00696 browse_ = true;
00697 gui_->recalculate_minimap();
00698
00699 const cursor::setter cursor_setter(cursor::WAIT);
00700
00701 turn_info turn_data(gamestate_,status_,*gui_,
00702 map_, teams_, player_number_, units_, replay_sender_, undo_stack_);
00703
00704 ai_interface::info ai_info(*gui_,map_,units_,teams_,player_number_,status_, turn_data, gamestate_);
00705 util::scoped_ptr<ai_interface> ai_obj(create_ai(current_team().ai_algorithm(),ai_info));
00706 ai_obj->user_interact().attach_handler(this);
00707 ai_obj->unit_recruited().attach_handler(this);
00708 ai_obj->unit_moved().attach_handler(this);
00709 ai_obj->enemy_attacked().attach_handler(this);
00710 ai_obj->play_turn();
00711 recorder.end_turn();
00712 turn_data.sync_network();
00713
00714 gui_->recalculate_minimap();
00715 ::clear_shroud(*gui_,map_,units_,teams_,player_number_-1);
00716 gui_->invalidate_unit();
00717 gui_->invalidate_game_status();
00718 gui_->invalidate_all();
00719 gui_->draw();
00720 gui_->delay(100);
00721 }
00722
00723 void playsingle_controller::handle_generic_event(const std::string& name){
00724 if (name == "ai_user_interact"){
00725 play_slice();
00726 gui_->draw();
00727 }
00728 }
00729
00730 void playsingle_controller::check_time_over(){
00731 if(!status_.next_turn()) {
00732
00733 if(non_interactive()) {
00734 std::cout << "time over (draw)\n";
00735 }
00736
00737 LOG_NG << "firing time over event...\n";
00738 game_events::fire("time over");
00739 LOG_NG << "done firing time over event...\n";
00740
00741 throw end_level_exception(DEFEAT);
00742 }
00743 }
00744
00745 bool playsingle_controller::can_execute_command(hotkey::HOTKEY_COMMAND command, int index) const
00746 {
00747 bool res = true;
00748 switch (command){
00749 case hotkey::HOTKEY_UNIT_HOLD_POSITION:
00750 case hotkey::HOTKEY_END_UNIT_TURN:
00751 case hotkey::HOTKEY_RECRUIT:
00752 case hotkey::HOTKEY_REPEAT_RECRUIT:
00753 case hotkey::HOTKEY_RECALL:
00754 return !browse_ && !linger_ && !events::commands_disabled;
00755 case hotkey::HOTKEY_ENDTURN:
00756 return (!browse_ || linger_) && !events::commands_disabled;
00757
00758 case hotkey::HOTKEY_DELAY_SHROUD:
00759 return !linger_ && (current_team().uses_fog() || current_team().uses_shroud());
00760 case hotkey::HOTKEY_UPDATE_SHROUD:
00761 return !linger_ && !events::commands_disabled && current_team().auto_shroud_updates() == false;
00762
00763
00764 case hotkey::HOTKEY_CREATE_UNIT:
00765 case hotkey::HOTKEY_CHANGE_UNIT_SIDE:
00766 return !events::commands_disabled && game_config::debug && map_.on_board(mouse_handler_.get_last_hex());
00767
00768 case hotkey::HOTKEY_LABEL_TEAM_TERRAIN:
00769 case hotkey::HOTKEY_LABEL_TERRAIN:
00770 res = !events::commands_disabled && map_.on_board(mouse_handler_.get_last_hex())
00771 && !gui_->shrouded(mouse_handler_.get_last_hex())
00772 && !is_observer();
00773 break;
00774
00775 case hotkey::HOTKEY_CONTINUE_MOVE: {
00776 if(browse_ || events::commands_disabled)
00777 return false;
00778
00779 if( (menu_handler_.current_unit(mouse_handler_) != units_.end())
00780 && (menu_handler_.current_unit(mouse_handler_)->second.move_interrupted()))
00781 return true;
00782 const unit_map::const_iterator i = units_.find(mouse_handler_.get_selected_hex());
00783 if (i == units_.end()) return false;
00784 return i->second.move_interrupted();
00785 }
00786 default: return play_controller::can_execute_command(command, index);
00787 }
00788 return res;
00789 }