84 #define ERR_NG LOG_STREAM(err, log_engine)
85 #define LOG_NG LOG_STREAM(info, log_engine)
92 std::string last_created_unit =
"";
93 std::string last_recruit =
"";
94 std::string last_variation =
"";
161 const auto& unit_dlg = units_dialog::build_unit_list_dialog(
unit_list);
163 if (unit_dlg->show() && unit_dlg->is_selected()) {
199 symbols[
"msg"] =
e.what();
200 const std::string
msg =
VGETTEXT(
"Could not save the map: $msg", symbols);
208 gui2::dialogs::preferences_dialog::display();
216 c[
"name"] =
"prototype of chat log";
228 ?
board().is_observer()
229 ?
_(
"Send to observers only")
230 :
_(
"Send to allies only")
248 if(
board().is_observer()) {
267 std::map<const unit_type*, t_string> err_msgs_map;
268 std::vector<const unit_type*> recruit_list;
269 std::vector<t_string> unknown_units;
275 int selected_index = -1,
i = 0;
280 recruit_list.push_back(
type);
283 unknown_units.emplace_back(
recruit);
291 if(
type->id() == last_recruit) {
298 if(!unknown_units.empty()) {
303 "Error: there’s an unknown unit type on your recruit list: $unknown_ids",
304 "Error: there are several unknown unit types on your recruit list: $unknown_ids",
305 unknown_units.size(),
306 {{
"unknown_ids", utils::format_conjunct_list(
"", unknown_units) }}
310 if(recruit_list.empty()) {
315 auto dlg = units_dialog::build_recruit_dialog(recruit_list, err_msgs_map, current_team);
316 dlg->set_selected_index(selected_index);
317 if (!dlg->show() && !dlg->is_selected()) {
321 const unit_type*
type = recruit_list[dlg->get_selected_index()];
322 last_recruit =
type->id();
325 if(err_msgs_map[
type].empty()) {
326 do_recruit(
type->id(), side_num, last_hex);
333 void menu_handler::repeat_recruit(
int side_num,
const map_location& last_hex)
335 team& current_team = board().get_team(side_num);
336 const std::string& last_recruit = current_team.
last_recruit();
337 if(last_recruit.empty())
return;
339 const auto validation = std::array
350 for(
const std::string&
err : validation) {
357 do_recruit(last_recruit, side_num, last_hex);
360 bool menu_handler::do_recruit(
const std::string&
type,
int side_num,
const map_location& target_hex)
373 if(
auto wb = pc_.get_whiteboard()) {
374 if(
wb->save_recruit(
type, side_num,
dst)) {
380 team& current_team = board().get_team(side_num);
391 if(pc_.get_disallow_recall()) {
396 team& current_team = board().get_team(side_num);
398 std::vector<unit_const_ptr> recall_list_team;
404 DBG_WB <<
"menu_handler::recall: Contents of wb-modified recall list:";
411 _(
"There are no troops available to recall.\n(You must have veteran survivors from a previous scenario.)"));
415 if(recall_list_team.empty()) {
420 const auto& dlg = units_dialog::build_recall_dialog(recall_list_team, current_team);
422 if(!dlg->show() || !dlg->is_selected()) {
426 int res = dlg->get_selected_index();
435 if(sel_unit->recall_cost() > -1) {
436 unit_cost = sel_unit->recall_cost();
439 int wb_gold = pc_.get_whiteboard() ? pc_.get_whiteboard()->get_spent_gold_for(side_num) : 0;
441 if(current_team.
gold() - wb_gold < unit_cost) {
443 i18n_symbols[
"cost"] = std::to_string(unit_cost);
444 std::string
msg =
VNGETTEXT(
"You must have at least 1 gold piece to recall a unit.",
445 "You must have at least $cost gold pieces to recall this unit.", unit_cost, i18n_symbols);
450 LOG_NG <<
"recall index: " << res;
467 if(!pc_.get_whiteboard()
468 || !pc_.get_whiteboard()->save_recall(*sel_unit, side_num, recall_location)) {
473 ERR_NG <<
"menu_handler::recall(): Unit does not exist in the recall list.";
479 void menu_handler::show_enemy_moves(
bool ignore_units,
int side_num)
486 gui_->unhighlight_reach();
489 for(
auto& u : pc_.get_units()) {
490 bool invisible = u.invisible(u.get_location());
492 if(board().get_team(side_num).
is_enemy(u.side()) && !gui_->fogged(u.get_location()) && !u.incapacitated()
496 =
pathfind::paths(u,
false,
true, gui_->viewing_team(), 0,
false, ignore_units);
498 gui_->highlight_another_reach(
path, hex_under_mouse);
502 gui_->invalidate(u.get_location());
507 const bool selected_hex_has_unit = mh.
hex_hosts_unit(hex_under_mouse);
509 if(selected_hex_has_unit) {
518 void menu_handler::toggle_shroud_updates(
int side_num)
520 team& current_team = board().get_team(side_num);
524 update_shroud_now(side_num);
531 void menu_handler::update_shroud_now(
int )
540 bool units_alive(
int side_num,
const unit_map& units)
542 for(
auto&
unit : units) {
551 bool partmoved_units(
552 int side_num,
const unit_map& units,
const game_board& board,
const std::shared_ptr<wb::manager>& whiteb)
554 for(
auto&
unit : units) {
569 int side_num,
const unit_map& units,
const game_board& board,
const std::shared_ptr<wb::manager>& whiteb)
571 for(
auto&
unit : units) {
574 && (!whiteb || !whiteb->unit_has_actions(&
unit))) {
584 bool menu_handler::end_turn(
int side_num)
589 reason =
_(
"You cannot end your turn yet!");
595 std::size_t team_num =
static_cast<std::size_t
>(side_num - 1);
596 if(team_num < pc_.get_teams().size() && pc_.get_teams()[team_num].no_turn_confirmation()) {
601 && (!pc_.get_whiteboard() || !pc_.get_whiteboard()->current_side_has_actions())
602 && units_alive(side_num, pc_.get_units())) {
604 _(
"You have not started your turn yet. Do you really want to end your turn?"),
605 message::yes_no_buttons);
611 else if(
prefs::get().yellow_confirm() && partmoved_units(side_num, pc_.get_units(), board(), pc_.get_whiteboard())) {
613 _(
"Some units have movement left. Do you really want to end your turn?"),
614 message::yes_no_buttons);
620 else if(
prefs::get().green_confirm() && unmoved_units(side_num, pc_.get_units(), board(), pc_.get_whiteboard())) {
622 _(
"Some units have not moved. Do you really want to end your turn?"),
623 message::yes_no_buttons);
631 if(pc_.get_whiteboard() && !pc_.get_whiteboard()->allow_end_turn()) {
638 void menu_handler::goto_leader(
int side_num)
641 if(
i != pc_.get_units().end() &&
i->is_visible_to_team(gui_->viewing_team(),
false)) {
646 void menu_handler::unit_description()
649 if(un != pc_.get_units().end()) {
657 if(pc_.get_map().on_board(
loc) ==
false || gui_->shrouded(
loc)) {
666 void menu_handler::rename_unit()
669 if(un == pc_.get_units().end() || gui_->viewing_team().side() != un->side()) {
673 if(un->unrenamable()) {
677 std::string name = un->name();
678 const std::string title(
_(
"Rename Unit"));
679 const std::string
label(
_(
"Name:"));
681 if(edit_text::execute(title,
label, name)) {
684 gui_->invalidate_unit();
690 const mouse_handler& mousehandler = pc_.get_mouse_handler_base();
691 const bool see_all = gui_->show_everything() || (pc_.is_replay() && pc_.get_replay_controller()->see_all());
694 if(res != pc_.get_units().end()) {
705 typedef std::tuple<const unit_type*, unit_race::GENDER, std::string> type_gender_variation;
714 type_gender_variation choose_unit()
718 const auto& create_dlg = units_dialog::build_create_dialog(types_list);
720 for (std::size_t
i = 0;
i < types_list.size();
i++) {
721 if (types_list[
i]->
id() == last_created_unit) {
722 create_dlg->set_selected_index(
i);
723 create_dlg->set_gender(last_gender);
724 create_dlg->set_variation(last_variation);
730 if(!create_dlg->show()) {
734 if(!create_dlg->is_selected()) {
738 const unit_type* ut = types_list[create_dlg->get_selected_index()];
739 last_created_unit = ut->
id();
740 last_gender = create_dlg->gender();
741 last_variation = create_dlg->variation();
744 if (create_dlg->is_selected()) {
745 info = type_gender_variation(ut, last_gender, last_variation);
747 ERR_NG <<
"Create unit dialog returned nonexistent or unusable unit_type id.";
758 void create_and_place(
762 const std::string& variation =
"")
770 "variation", variation,
787 if(
const auto& [
type, gender, variation] = choose_unit();
type !=
nullptr) {
788 create_and_place(destination, *
type, gender, variation);
796 if(
i == pc_.get_units().end()) {
797 if(!pc_.get_map().is_village(
loc)) {
805 if(
team >
static_cast<int>(pc_.get_teams().size())) {
810 int side =
i->side();
812 if(side >
static_cast<int>(pc_.get_teams().size())) {
817 if(pc_.get_map().is_village(
loc)) {
829 void menu_handler::label_terrain(
mouse_handler& mousehandler,
bool team_only)
832 if(pc_.get_map().on_board(
loc) ==
false) {
837 std::string
label = old_label ? old_label->
text() :
"";
839 if(edit_label::execute(
label, team_only)) {
840 std::string team_name;
844 team_name = gui_->labels().team_name();
848 const terrain_label* res = gui_->labels().set_label(
loc,
label, gui_->viewing_team_index(), team_name, color);
855 void menu_handler::clear_labels()
857 if(!board().is_observer()) {
860 _(
"Are you sure you want to clear map labels?"),
861 message::yes_no_buttons
865 std::string viewing_team = gui_->viewing_team().team_name();
866 gui_->labels().clear(viewing_team,
false);
872 void menu_handler::label_settings()
874 if(label_settings::execute(board())) {
875 gui_->labels().recalculate_labels();
882 if(
i == pc_.get_units().end() || !
i->move_interrupted()) {
884 if(
i == pc_.get_units().end() || !
i->move_interrupted()) {
888 move_unit_to_loc(
i,
i->get_interrupted_move(),
true, side_num, mousehandler);
891 void menu_handler::move_unit_to_loc(
898 assert(ui != pc_.get_units().end());
902 if(route.
steps.empty()) {
906 assert(route.
steps.front() == ui->get_location());
908 gui_->set_route(&route);
909 gui_->unhighlight_reach();
912 LOG_NG <<
"move_unit_to_loc " << route.
steps.front() <<
" to " << route.
steps.back();
917 gui_->set_route(
nullptr);
918 gui_->invalidate_game_status();
927 bool wait_blocker_move =
true;
928 std::set<map_location> fully_moved;
931 bool blocked_unit =
false;
934 blocked_unit =
false;
935 for(
auto&
unit : pc_.get_units()) {
943 if(goto_loc == current_loc) {
948 if(!pc_.get_map().on_board(goto_loc)) {
953 if(fully_moved.count(current_loc)) {
959 if(route.
steps.size() <= 1) {
960 fully_moved.insert(current_loc);
966 pathfind::marked_route::mark_map::const_iterator
w = route.
marks.begin();
967 for(;
w != route.
marks.end(); ++
w) {
968 if(
w->second.turns == 1) {
969 next_stop =
w->first;
974 if(next_stop == current_loc) {
975 fully_moved.insert(current_loc);
981 if(pc_.get_units().count(next_stop)) {
983 if(wait_blocker_move)
987 gui_->set_route(&route);
990 LOG_NG <<
"execute goto from " << route.
steps.front() <<
" to " << route.
steps.back();
997 wait_blocker_move =
true;
1001 if(!change && wait_blocker_move) {
1003 wait_blocker_move =
false;
1006 }
while(change && blocked_unit);
1009 gui_->set_route(
nullptr);
1010 gui_->invalidate_game_status();
1013 void menu_handler::toggle_ellipses()
1016 gui_->invalidate_all();
1019 void menu_handler::toggle_grid()
1022 gui_->invalidate_all();
1025 void menu_handler::unit_hold_position(
mouse_handler& mousehandler,
int side_num)
1028 if(un != pc_.get_units().end() && un->side() == side_num && un->movement_left() >= 0) {
1029 un->toggle_hold_position();
1034 if(un->hold_position()) {
1043 if(un != pc_.get_units().end() && un->side() == side_num && un->movement_left() >= 0) {
1044 un->toggle_user_end_turn();
1049 if(un->user_end_turn()) {
1061 void menu_handler::search()
1063 std::ostringstream
msg;
1065 if(last_search_hit_.valid()) {
1066 msg <<
" [" << last_search_ <<
"]";
1072 bool menu_handler::do_speak()
1076 return chat_handler::do_speak(
1077 textbox_info_.box()->text(), textbox_info_.check() !=
nullptr ? textbox_info_.check()->checked() :
false);
1080 void menu_handler::add_chat_message(
const std::chrono::system_clock::time_point& time,
1081 const std::string& speaker,
1086 gui_->get_chat_manager().add_chat_message(time, speaker, side,
message,
type,
false);
1113 using chmap::get_commands_list;
1114 using chmap::command_failed;
1120 chat_command_handler::command_handler
h,
1121 const std::string&
help =
"",
1122 const std::string& usage =
"",
1123 const std::string& flags =
"")
1125 chmap::register_command(cmd,
h,
help, usage, flags +
"N");
1130 chmap::register_alias(to_cmd, cmd);
1135 return chmap::get_arg(
i);
1140 return chmap::get_cmd();
1145 return chmap::get_data(
n);
1149 using chmap::register_command;
1150 using chmap::register_alias;
1152 using chmap::is_enabled;
1153 using chmap::command_failed_need_arg;
1161 void do_controller();
1163 void do_foreground();
1166 void do_benchmark();
1168 void do_save_quit();
1170 void do_ignore_replay_errors();
1172 void do_next_level();
1173 void do_choose_level();
1175 void do_turn_limit();
1179 void do_unsafe_lua();
1181 void do_set_alias();
1185 void do_control_dialog();
1190 void do_undiscover();
1196 void do_toggle_draw_coordinates();
1197 void do_toggle_draw_terrain_codes();
1198 void do_toggle_draw_num_of_bitmaps();
1199 void do_toggle_whiteboard();
1200 void do_whiteboard_options();
1204 return _(
"(D) — debug only, (N) — network only, (A) — admin only");
1207 using chat_command_handler::get_command_flags_description;
1210 std::string space(
" ");
1211 return (
c.has_flag(
'D') ? space +
_(
"(debug command)") :
"")
1212 + (
c.has_flag(
'N') ? space +
_(
"(network only)") :
"")
1213 + (
c.has_flag(
'A') ? space +
_(
"(admin only)") :
"")
1214 + (
c.has_flag(
'S') ? space +
_(
"(not during other events)") :
"");
1217 using map::is_enabled;
1221 || (
c.has_flag(
'N') && !menu_handler_.pc_.is_networked_mp())
1228 menu_handler_.add_chat_message(std::chrono::system_clock::now(), title, 0,
message);
1233 chat_command_handler::init_map();
1235 chmap::get_command(
"log")->flags =
"";
1236 chmap::get_command(
"version")->flags =
"";
1237 chmap::get_command(
"ignore")->flags =
"";
1238 chmap::get_command(
"friend")->flags =
"";
1239 chmap::get_command(
"remove")->flags =
"";
1241 chmap::set_cmd_prefix(
":");
1242 chmap::set_cmd_flag(
true);
1244 register_command(
"refresh", &console_handler::do_refresh,
_(
"Refresh gui."));
1245 register_command(
"droid", &console_handler::do_droid,
_(
"Switch a side to/from AI control."),
1249 _(
"[<side> [on/off/full]]\n“on” = enable but retain vision, “full” = as if it’s controlled by another player"));
1250 register_command(
"terrain", &console_handler::do_terrain,
_(
"Change terrain type of current hex"),
1252 _(
"<terrain type> [both|base|overlay]"),
"DS");
1253 register_command(
"idle", &console_handler::do_idle,
_(
"Switch a side to/from idle state."),
1257 _(
"command_idle^[<side> [on/off]]"));
1258 register_command(
"theme", &console_handler::do_theme,
_(
"Change the in-game theme."));
1259 register_command(
"control", &console_handler::do_control,
1260 _(
"Assign control of a side to a different player or observer."),
_(
"<side> <nickname>"),
"N");
1261 register_command(
"controller", &console_handler::do_controller,
_(
"Query the controller status of a side."),
1263 register_command(
"clear", &console_handler::do_clear,
_(
"Clear chat history."));
1264 register_command(
"foreground", &console_handler::do_foreground,
_(
"Debug foreground terrain."),
"",
"D");
1266 "layers", &console_handler::do_layers,
_(
"Debug layers from terrain under the mouse."),
"",
"D");
1267 register_command(
"fps", &console_handler::do_fps,
_(
"Display and log fps (Frames Per Second)."));
1268 register_command(
"benchmark", &console_handler::do_benchmark,
_(
"Similar to the ‘fps’ command, but also forces everything to redraw instead of only things that have changed."));
1269 register_command(
"save", &console_handler::do_save,
_(
"Save game."));
1270 register_alias(
"save",
"w");
1271 register_command(
"quit", &console_handler::do_quit,
_(
"Quit game."));
1273 register_alias(
"quit",
"q!");
1274 register_command(
"save_quit", &console_handler::do_save_quit,
_(
"Save and quit."));
1275 register_alias(
"save_quit",
"wq");
1276 register_command(
"ignore_replay_errors", &console_handler::do_ignore_replay_errors,
_(
"Ignore replay errors."));
1277 register_command(
"nosaves", &console_handler::do_nosaves,
_(
"Disable autosaves."));
1278 register_command(
"next_level", &console_handler::do_next_level,
1279 _(
"Advance to the next scenario, or scenario identified by ‘id’"),
_(
"<id>"),
"DS");
1280 register_alias(
"next_level",
"n");
1281 register_command(
"choose_level", &console_handler::do_choose_level,
_(
"Choose next scenario"),
"",
"DS");
1282 register_alias(
"choose_level",
"cl");
1283 register_command(
"turn", &console_handler::do_turn,
1284 _(
"Change turn number (and time of day), or increase by one if no number is specified."),
_(
"[turn]"),
1286 register_command(
"turn_limit", &console_handler::do_turn_limit,
1287 _(
"Change turn limit, or turn the turn limit off if no number is specified or it’s −1."),
_(
"[limit]"),
1289 register_command(
"debug", &console_handler::do_debug,
_(
"Turn debug mode on."));
1290 register_command(
"nodebug", &console_handler::do_nodebug,
_(
"Turn debug mode off."),
"",
"D");
1292 "lua", &console_handler::do_lua,
_(
"Execute a Lua statement."),
_(
"<command>[;<command>...]"),
"DS");
1294 "unsafe_lua", &console_handler::do_unsafe_lua,
_(
"Grant higher privileges to Lua scripts."),
"",
"D");
1295 register_command(
"custom", &console_handler::do_custom,
_(
"Set the command used by the custom command hotkey"),
1296 _(
"<command>[;<command>...]"));
1297 register_command(
"give_control", &console_handler::do_control_dialog,
1298 _(
"Invoke a dialog allowing changing control of MP sides."),
"",
"N");
1299 register_command(
"inspect", &console_handler::do_inspect,
_(
"Launch the gamestate inspector"),
"",
"D");
1301 "alias", &console_handler::do_set_alias,
_(
"Set or show alias to a command"),
_(
"<name>[=<command>]"));
1303 "set_var", &console_handler::do_set_var,
_(
"Set a scenario variable."),
_(
"<var>=<value>"),
"DS");
1304 register_command(
"show_var", &console_handler::do_show_var,
_(
"Show a scenario variable."),
_(
"<var>"),
"D");
1305 register_command(
"unit", &console_handler::do_unit,
1307 _(
"Modify a unit variable. (Only top level keys are supported, and advances=<number>.)"),
1308 _(
"<var>=<value>"),
"DS");
1314 register_command(
"discover", &console_handler::do_discover,
_(
"Discover all units in help."),
"");
1315 register_command(
"undiscover", &console_handler::do_undiscover,
_(
"‘Undiscover’ all units in help."),
"");
1316 register_command(
"create", &console_handler::do_create,
_(
"Create a unit."),
_(
"<unit type id>"),
"DS");
1317 register_command(
"fog", &console_handler::do_fog,
_(
"Toggle fog for the current player."),
"",
"DS");
1318 register_command(
"shroud", &console_handler::do_shroud,
_(
"Toggle shroud for the current player."),
"",
"DS");
1319 register_command(
"gold", &console_handler::do_gold,
_(
"Give gold to the current player."),
_(
"<amount>"),
"DS");
1320 register_command(
"throw", &console_handler::do_event,
_(
"Fire a game event."),
_(
"<event name>"),
"DS");
1321 register_alias(
"throw",
"fire");
1322 register_command(
"show_coordinates", &console_handler::do_toggle_draw_coordinates,
1323 _(
"Toggle overlaying of x,y coordinates on hexes."));
1324 register_alias(
"show_coordinates",
"sc");
1325 register_command(
"show_terrain_codes", &console_handler::do_toggle_draw_terrain_codes,
1326 _(
"Toggle overlaying of terrain codes on hexes."));
1327 register_alias(
"show_terrain_codes",
"tc");
1328 register_command(
"show_num_of_bitmaps", &console_handler::do_toggle_draw_num_of_bitmaps,
1329 _(
"Toggle overlaying of number of bitmaps on hexes."));
1330 register_alias(
"show_num_of_bitmaps",
"bn");
1331 register_command(
"whiteboard", &console_handler::do_toggle_whiteboard,
_(
"Toggle planning mode."));
1332 register_alias(
"whiteboard",
"wb");
1334 "whiteboard_options", &console_handler::do_whiteboard_options,
_(
"Access whiteboard options dialog."));
1335 register_alias(
"whiteboard_options",
"wbo");
1337 if(
auto alias_list =
prefs::get().get_alias()) {
1338 for(
const auto& [key, value] : alias_list->attribute_range()) {
1339 register_alias(value, key);
1349 void menu_handler::send_chat_message(
const std::string&
message,
bool allies_only)
1354 auto now = std::chrono::system_clock::now();
1357 const int side = board().
is_observer() ? 0 : gui_->viewing_team().side();
1358 if(!board().is_observer()) {
1365 if(board().is_observer()) {
1368 cfg[
"to_sides"] = gui_->viewing_team().allied_human_teams();
1374 add_chat_message(now,
cfg[
"id"], side,
message,
1378 void menu_handler::do_search(
const std::string& new_search)
1380 if(new_search.empty() ==
false && new_search != last_search_)
1381 last_search_ = new_search;
1383 if(last_search_.empty())
1389 std::vector<std::string> args =
utils::split(last_search_,
',');
1390 if(args.size() == 2) {
1392 x = lexical_cast_default<int>(args[0], 0) - 1;
1393 y = lexical_cast_default<int>(args[1], 0) - 1;
1394 if(x >= 0 && x < pc_.get_map().w() && y >= 0 && y < pc_.get_map().h()) {
1407 loc.
x = (
loc.
x + 1) % pc_.get_map().w();
1409 loc.
y = (
loc.
y + 1) % pc_.get_map().h();
1412 if(!gui_->shrouded(
loc)) {
1415 const std::string& label_text =
label->text().str();
1421 if(!gui_->fogged(
loc)) {
1423 if(ui != pc_.get_units().end()) {
1424 const std::string&
unit_name = ui->name();
1426 if(!gui_->viewing_team().is_enemy(ui->side())
1427 || !ui->invisible(ui->get_location())) {
1439 last_search_hit_ =
loc;
1441 gui_->highlight_hex(
loc);
1446 symbols[
"search"] = last_search_;
1447 const std::string
msg =
VGETTEXT(
"Could not find label or unit "
1448 "containing the string ‘$search’.",
1454 void menu_handler::do_command(
const std::string& str)
1460 std::vector<std::string> menu_handler::get_commands_list()
1471 void console_handler::do_refresh()
1476 menu_handler_.gui_->create_buttons();
1477 menu_handler_.gui_->queue_rerender();
1480 void console_handler::do_droid()
1483 const std::string side_s = get_arg(1);
1484 std::string action = get_arg(2);
1485 std::transform(action.begin(), action.end(), action.begin(), tolower);
1487 const unsigned int side = side_s.empty() ? team_num_ : lexical_cast_default<unsigned int>(side_s);
1488 const bool is_your_turn = menu_handler_.pc_.current_side() ==
static_cast<int>(menu_handler_.gui_->viewing_team().side());
1489 team&
team = menu_handler_.board().get_team(side);
1492 symbols[
"side"] = std::to_string(side);
1494 if(side < 1 || side > menu_handler_.pc_.get_teams().size()) {
1495 command_failed(
VGETTEXT(
"Can’t droid invalid side: ‘$side’.", symbols));
1498 command_failed(
VGETTEXT(
"Can’t droid networked side: ‘$side’.", symbols));
1501 bool changed =
false;
1508 if(action ==
"on") {
1509 if(is_ai && !is_your_turn) {
1510 command_failed(
_(
"It is not allowed to change a side from AI to human control when it’s not your turn."));
1513 if(!is_human || !is_droid) {
1518 menu_handler_.pc_.send_to_wesnothd(
config {
"change_controller",
config {
"side", side,
"player",
prefs::get().
login(),
"to", side_controller::human}});
1520 print(get_cmd(),
VGETTEXT(
"Side ‘$side’ controller is now controlled by: AI.", symbols));
1522 print(get_cmd(),
VGETTEXT(
"Side ‘$side’ is already droided.", symbols));
1524 }
else if(action ==
"off") {
1525 if(is_ai && !is_your_turn) {
1526 command_failed(
_(
"It is not allowed to change a side from AI to human control when it’s not your turn."));
1529 if(!is_human || !is_proxy_human) {
1534 menu_handler_.pc_.send_to_wesnothd(
config {
"change_controller",
config {
"side", side,
"player",
prefs::get().
login(),
"to", side_controller::human}});
1536 print(get_cmd(),
VGETTEXT(
"Side ‘$side’ controller is now controlled by: human.", symbols));
1538 print(get_cmd(),
VGETTEXT(
"Side ‘$side’ is already not droided.", symbols));
1540 }
else if(action ==
"full") {
1542 command_failed(
_(
"It is not allowed to change a side from human to AI control when it’s not your turn."));
1545 if(!is_ai || !is_droid) {
1549 if(is_human || is_proxy_human) {
1550 menu_handler_.pc_.send_to_wesnothd(
config {
"change_controller",
config {
"side", side,
"player",
prefs::get().
login(),
"to", side_controller::ai}});
1552 print(get_cmd(),
VGETTEXT(
"Side ‘$side’ controller is now fully controlled by: AI.", symbols));
1554 print(get_cmd(),
VGETTEXT(
"Side ‘$side’ is already fully AI controlled.", symbols));
1556 }
else if(action ==
"") {
1557 if(is_ai && !is_your_turn) {
1558 command_failed(
_(
"It is not allowed to change a side from AI to human control when it’s not your turn."));
1561 if(is_ai || is_droid) {
1566 menu_handler_.pc_.send_to_wesnothd(
config {
"change_controller",
config {
"side", side,
"player",
prefs::get().
login(),
"to", side_controller::human}});
1568 print(get_cmd(),
VGETTEXT(
"Side ‘$side’ controller is now controlled by: human.", symbols));
1574 menu_handler_.pc_.send_to_wesnothd(
config {
"change_controller",
config {
"side", side,
"player",
prefs::get().
login(),
"to", side_controller::human}});
1576 print(get_cmd(),
VGETTEXT(
"Side ‘$side’ controller is now controlled by: AI.", symbols));
1579 print(get_cmd(),
VGETTEXT(
"Invalid action provided for side ‘$side’. Valid actions are: on, off, full.", symbols));
1582 if(team_num_ == side && changed) {
1584 psc->set_player_type_changed();
1588 command_failed(
VGETTEXT(
"Side ‘$side’ is not a human or AI player.", symbols));
1591 menu_handler_.textbox_info_.close();
1594 void console_handler::do_terrain()
1598 const std::string mode_str = get_arg(2);
1608 "mode_str", mode_str,
1613 void console_handler::do_idle()
1616 const std::string side_s = get_arg(1);
1617 const std::string action = get_arg(2);
1619 const unsigned int side = side_s.empty() ? team_num_ : lexical_cast_default<unsigned int>(side_s);
1620 team&
team = menu_handler_.board().get_team(side);
1622 if(side < 1 || side > menu_handler_.pc_.get_teams().size()) {
1624 symbols[
"side"] = side_s;
1625 command_failed(
VGETTEXT(
"Can’t idle invalid side: ‘$side’.", symbols));
1629 symbols[
"side"] = std::to_string(side);
1630 command_failed(
VGETTEXT(
"Can’t idle networked side: ‘$side’.", symbols));
1634 symbols[
"side"] = std::to_string(side);
1635 command_failed(
VGETTEXT(
"Can’t idle local ai side: ‘$side’.", symbols));
1638 if(
team.
is_idle() ? action ==
" on" : action ==
" off") {
1643 if(team_num_ == side) {
1645 psc->set_player_type_changed();
1649 menu_handler_.textbox_info_.close();
1652 void console_handler::do_theme()
1657 void console_handler::do_control()
1660 if(!menu_handler_.pc_.is_networked_mp()) {
1664 const std::string side = get_arg(1);
1665 const std::string player = get_arg(2);
1666 if(player.empty()) {
1667 command_failed_need_arg(2);
1671 unsigned int side_num;
1673 side_num = lexical_cast<unsigned int>(side);
1675 const auto& teams = menu_handler_.pc_.get_teams();
1678 if(it_t == teams.end()) {
1680 symbols[
"side"] = side;
1681 command_failed(
VGETTEXT(
"Can’t change control of invalid side: ‘$side’.", symbols));
1684 side_num = it_t->side();
1688 if(side_num < 1 || side_num > menu_handler_.pc_.get_teams().size()) {
1690 symbols[
"side"] = side;
1691 command_failed(
VGETTEXT(
"Can’t change control of out-of-bounds side: ‘$side’.", symbols));
1695 menu_handler_.request_control_change(side_num, player);
1696 menu_handler_.textbox_info_.close();
1699 void console_handler::do_controller()
1701 const std::string side = get_arg(1);
1702 unsigned int side_num;
1704 side_num = lexical_cast<unsigned int>(side);
1707 symbols[
"side"] = side;
1708 command_failed(
VGETTEXT(
"Can’t query control of invalid side: ‘$side’.", symbols));
1712 if(side_num < 1 || side_num > menu_handler_.pc_.get_teams().size()) {
1714 symbols[
"side"] = side;
1715 command_failed(
VGETTEXT(
"Can’t query control of out-of-bounds side: ‘$side’.", symbols));
1720 if(!menu_handler_.board().get_team(side_num).is_proxy_human()) {
1724 if(menu_handler_.board().get_team(side_num).is_network()) {
1725 report +=
" (networked)";
1728 print(get_cmd(), report);
1731 void console_handler::do_clear()
1733 menu_handler_.gui_->get_chat_manager().clear_chat_messages();
1736 void console_handler::do_foreground()
1739 menu_handler_.gui_->invalidate_all();
1742 void console_handler::do_layers()
1744 display& disp = *(menu_handler_.gui_);
1758 if(menu_handler_.pc_.get_map().on_board_with_border(
loc)) {
1759 terrain_layers::display(disp,
loc);
1763 void console_handler::do_fps()
1768 void console_handler::do_benchmark()
1773 void console_handler::do_save()
1775 menu_handler_.pc_.do_consolesave(get_data());
1778 void console_handler::do_save_quit()
1784 void console_handler::do_quit()
1789 void console_handler::do_ignore_replay_errors()
1794 void console_handler::do_nosaves()
1799 void console_handler::do_next_level()
1804 void console_handler::do_choose_level()
1806 std::string
tag = menu_handler_.pc_.get_classification().get_tagname();
1807 std::vector<std::string> options;
1809 if(
tag !=
"multiplayer") {
1811 const std::string&
id = sc[
"id"];
1812 options.push_back(
id);
1813 if(
id == menu_handler_.gamedata().next_scenario()) {
1820 std::string scenario_id = menu_handler_.pc_.get_mp_settings().mp_scenario;
1821 if(
auto this_scenario = menu_handler_.game_config_.find_child(
tag,
"id", scenario_id)) {
1822 std::string addon_id = this_scenario[
"addon_id"].str();
1824 if(sc[
"addon_id"] == addon_id) {
1825 std::string
id = sc[
"id"];
1826 options.push_back(
id);
1827 if(
id == menu_handler_.gamedata().next_scenario()) {
1834 std::sort(options.begin(), options.end());
1835 int choice = std::distance(options.begin(), std::lower_bound(options.begin(), options.end(), next));
1847 if(std::size_t(choice) < options.size()) {
1852 void console_handler::do_turn()
1854 tod_manager& tod_man = menu_handler_.gamestate().tod_manager_;
1856 int turn = tod_man.
turn() + 1;
1857 const std::string&
data = get_data();
1859 turn = lexical_cast_default<int>(
data, 1);
1864 void console_handler::do_turn_limit()
1866 int limit = get_data().empty() ? -1 : lexical_cast_default<int>(get_data(), 1);
1870 void console_handler::do_debug()
1873 print(get_cmd(),
_(
"Debug mode activated!"));
1876 command_failed(
_(
"Debug mode not available in network games"));
1880 void console_handler::do_nodebug()
1883 print(get_cmd(),
_(
"Debug mode deactivated!"));
1888 void console_handler::do_lua()
1890 if(!menu_handler_.gamestate().lua_kernel_) {
1897 void console_handler::do_unsafe_lua()
1899 if(!menu_handler_.gamestate().lua_kernel_) {
1904 _(
"Executing Lua code in in this manner opens your computer to potential security breaches from any "
1905 "malicious add-ons or other programs you may have installed.\n\n"
1906 "Do not continue unless you really know what you are doing."), message::ok_cancel_buttons);
1909 print(get_cmd(),
_(
"Unsafe mode enabled!"));
1910 menu_handler_.gamestate().lua_kernel_->load_package();
1914 void console_handler::do_custom()
1919 void console_handler::do_set_alias()
1921 const std::string
data = get_data();
1923 const std::string alias(
data.begin(), j);
1924 if(j !=
data.end()) {
1925 const std::string command(j + 1,
data.end());
1926 if(!command.empty()) {
1927 register_alias(command, alias);
1931 register_alias(alias, alias);
1939 const std::string command = chmap::get_actual_cmd(alias);
1940 print(get_cmd(),
"'" + alias +
"'" +
" = " +
"'" + command +
"'");
1944 void console_handler::do_set_var()
1946 const std::string
data = get_data();
1948 command_failed_need_arg(1);
1953 if(j !=
data.end()) {
1954 const std::string name(
data.begin(), j);
1955 const std::string value(j + 1,
data.end());
1958 command_failed(
_(
"Variable not found"));
1962 void console_handler::do_show_var()
1967 void console_handler::do_inspect()
1970 gamestate_inspector::display(
1974 void console_handler::do_control_dialog()
1976 mp_change_control::display(menu_handler_);
1979 void console_handler::do_unit()
1987 if(
i == menu_handler_.pc_.get_units().end()) {
1989 symbols[
"unit"] = get_arg(1);
1991 "Debug command ‘unit: $unit’ failed: no unit selected or hovered over.",
1997 const std::string
data = get_data(1);
1999 if(parameters.size() < 2) {
2003 if(parameters[0] ==
"alignment") {
2007 symbols[
"alignment"] = get_arg(1);
2009 "Invalid alignment: ‘$alignment’, needs to be one of lawful, neutral, chaotic, or liminal.",
2019 "name", parameters[0],
2020 "value", parameters[1],
2025 void console_handler::do_discover()
2027 for(
const unit_type_data::unit_type_map::value_type&
i :
unit_types.
types()) {
2032 void console_handler::do_undiscover()
2035 _(
"Do you wish to clear all of your discovered units from help?"), message::yes_no_buttons);
2042 void console_handler::do_create()
2046 if(menu_handler_.pc_.get_map().on_board(
loc)) {
2049 command_failed(
_(
"Invalid unit type"));
2054 create_and_place(
loc, *ut);
2056 command_failed(
_(
"Invalid location"));
2060 void console_handler::do_fog()
2065 void console_handler::do_shroud()
2070 void console_handler::do_gold()
2075 void console_handler::do_event()
2080 void console_handler::do_toggle_draw_coordinates()
2083 menu_handler_.gui_->invalidate_all();
2085 void console_handler::do_toggle_draw_terrain_codes()
2088 menu_handler_.gui_->invalidate_all();
2091 void console_handler::do_toggle_draw_num_of_bitmaps()
2094 menu_handler_.gui_->invalidate_all();
2097 void console_handler::do_toggle_whiteboard()
2099 if(
const std::shared_ptr<wb::manager>& whiteb = menu_handler_.pc_.get_whiteboard()) {
2100 whiteb->set_active(!whiteb->is_active());
2101 if(whiteb->is_active()) {
2102 print(get_cmd(),
_(
"Planning mode activated!"));
2103 whiteb->print_help_once();
2105 print(get_cmd(),
_(
"Planning mode deactivated!"));
2110 void console_handler::do_whiteboard_options()
2112 if(menu_handler_.pc_.get_whiteboard()) {
2113 menu_handler_.pc_.get_whiteboard()->options_dlg();
2122 add_chat_message(std::chrono::system_clock::now(),
"wfl", 0, result.
to_debug_string());
2129 void menu_handler::user_command()
2134 void menu_handler::request_control_change(
int side_num,
const std::string& player)
2136 std::string side = std::to_string(side_num);
2137 if(board().get_team(side_num).is_local_human() && player ==
prefs::get().login()) {
2143 pc_.send_to_wesnothd(
config {
"change_controller",
config {
"side", side,
"player", player}});
2147 void menu_handler::custom_command()
2150 do_command(command);
2154 void menu_handler::ai_formula()
2156 if(!pc_.is_networked_mp()) {
2161 void menu_handler::clear_messages()
2163 gui_->get_chat_manager().clear_chat_messages();
2168 pc_.send_to_wesnothd(
cfg);
static bool is_enemy(std::size_t side, std::size_t other_side)
Various functions related to moving units.
A config object defines a single node in a WML file, with access to child nodes.
child_itors child_range(std::string_view key)
int village_owner(const map_location &loc) const
Given the location of a village, will return the 1-based number of the team that currently owns it,...
bool is_observer() const
Check if we are an observer in this game.
can_move_result unit_can_move(const unit &u) const
Work out what u can do - this does not check which player's turn is currently active,...
virtual const unit_map & units() const =0
Sort-of-Singleton that many classes, both GUI and non-GUI, use to access the game data.
const team & viewing_team() const
@ DEBUG_COORDINATES
Overlays x,y coords on tiles.
@ DEBUG_BENCHMARK
Toggle to continuously redraw the whole map.
@ DEBUG_NUM_BITMAPS
Overlays number of bitmaps on tiles.
@ DEBUG_FOREGROUND
Separates background and foreground terrain layers.
@ DEBUG_TERRAIN_CODES
Overlays terrain codes on tiles.
void scroll_to_tile(const map_location &loc, SCROLL_TYPE scroll_type=ONSCREEN, bool check_fogged=true, bool force=true)
Scroll such that location loc is on-screen.
const display_context & context() const
void queue_rerender()
Marks everything for rendering including all tiles and sidebar.
virtual std::string get_arg(unsigned i) const
std::string get_flags_description() const
virtual std::string get_cmd() const
console_handler(menu_handler &menu_handler)
void print(const std::string &title, const std::string &message)
virtual void register_alias(const std::string &to_cmd, const std::string &cmd)
bool is_enabled(const chmap::command &c) const
virtual std::string get_data(unsigned n=1) const
menu_handler & menu_handler_
std::string get_command_flags_description(const chmap::command &c) const
virtual void register_command(const std::string &cmd, chat_command_handler::command_handler h, const std::string &help="", const std::string &usage="", const std::string &flags="")
map_command_handler< console_handler > chmap
const unsigned int team_num_
bool dispatch(std::string cmd)
std::vector< std::string > get_commands_list() const
game_board & board() const
gui::floating_textbox & get_textbox()
gui::floating_textbox textbox_info_
void show_statistics(int side_num)
void recruit(int side_num, const map_location &last_hex)
game_state & gamestate() const
void disable_units_highlight()
Use this to disable hovering an unit from highlighting its movement range.
void set_current_paths(const pathfind::paths &new_paths)
pathfind::marked_route get_route(const unit *un, map_location go_to, const team &team) const
map_location get_selected_hex() const
const map_location hovered_hex() const
Uses SDL and game_display::hex_clicked_on to fetch the hex the mouse is hovering, if applicable.
const map_location & get_last_hex() const
bool hex_hosts_unit(const map_location &hex) const
Unit exists on the hex, no matter if friend or foe.
void cycle_units(const bool browse, const bool reverse=false)
unit_map::iterator find_visible_unit(const map_location &loc, const team ¤t_team, bool see_all=false)
void scroll_to_leader(int side, SCROLL_TYPE scroll_type=ONSCREEN, bool force=true)
Scrolls to the leader of a certain side.
virtual const std::set< std::string > & observers() const override
virtual void select_hex(map_location hex) override
Function to display a location as selected.
std::string write() const
file_dialog & set_extension(const std::string &value)
Sets allowed file extensions for file names in save mode.
file_dialog & set_path(const std::string &value)
Sets the initial file selection.
file_dialog & set_title(const std::string &value)
Sets the current dialog title text.
file_dialog & set_save_mode(bool value)
Sets the dialog's behavior on non-existent file name inputs.
std::string path() const
Gets the current file selection.
Main class to show messages to the user.
bool show(const unsigned auto_close_time=0)
Shows the window.
int selected_index() const
Returns the selected item index after displaying.
void set_selected_index(int index)
Sets the initially selected item index (-1 by default).
void show(gui::TEXTBOX_MODE mode, const std::string &label, const std::string &check_label, bool checked, game_display &gui)
std::vector< team > & get_teams()
void show_objectives() const
statistics_t & statistics()
events::mouse_handler & get_mouse_handler_base() override
Get a reference to a mouse handler member a derived class uses.
const gamemap & get_map() const
void refresh_objectives() const
Reevaluate [show_if] conditions and build a new objectives string.
void notify_event(const std::string &name, const config &data)
static plugins_manager * get()
std::set< std::string > & encountered_units()
void add_alias(const std::string &alias, const std::string &command)
void set_message_private(bool value)
void set_show_fps(bool value)
bool empty() const
Is it empty?
static config get_recall(const std::string &unit_id, const map_location &loc, const map_location &from)
static config get_recruit(const std::string &type_id, const map_location &loc, const map_location &from)
static config get_update_shroud()
Records that the player has manually updated fog/shroud.
static config get_auto_shroud(bool turned_on, bool block_undo=true)
Records that the player has toggled automatic shroud updates.
void add_rename(const std::string &name, const map_location &loc)
void add_label(const terrain_label *)
void speak(const config &cfg)
void clear_labels(const std::string &, bool)
static synced_state get_synced_state()
static bool run_and_throw(const std::string &commandname, const config &data, action_spectator &spectator=get_default_spectator())
This class stores all the data for a single 'side' (in game nomenclature).
bool is_proxy_human() const
bool auto_shroud_updates() const
const std::string & team_name() const
bool is_local_human() const
void set_last_recruit(const std::string &u_type)
const std::string & save_id() const
static color_t get_side_color(int side)
void increment_action_bonus_count()
recall_list_manager & recall_list()
const std::string & last_recruit() const
To store label data Class implements logic for rendering.
const t_string & text() const
Container associating units to locations.
const unit_type * find(const std::string &key, unit_type::BUILD_STATUS status=unit_type::FULL) const
Finds a unit_type by its id() and makes sure it is built to the specified level.
const std::vector< const unit_type * > types_list() const
const unit_type_map & types() const
A single unit type that the player may recruit.
const std::string & id() const
The id for this unit_type.
This class represents a single unit of a specific type.
A variable-expanding proxy for the config class.
static vconfig empty_vconfig()
An object representing the state of the game, providing access to the map and basic information.
std::string to_debug_string(bool verbose=false, formula_seen_stack *seen=nullptr) const
Various functions related to the creation of units (recruits, recalls, and placed units).
static void print(std::stringstream &sstr, const std::string &queue, const std::string &id)
Contains the exception interfaces used to signal completion of a scenario, campaign or turn.
void throw_quit_game_exception()
int dispatch(lua_State *L)
static std::string _(const char *str)
bool user_end_turn() const
Check whether the user ended their turn.
const std::string & id() const
Gets this unit's id.
int side() const
The side this unit belongs to.
const t_string & name() const
Gets this unit's translatable display name.
const map_location & get_location() const
The current map location this unit is at.
bool has_moved() const
Checks if this unit has moved.
void set_goto(const map_location &new_goto)
Sets this unit's long term destination.
int movement_left() const
Gets how far a unit can move, considering the incapacitated flag.
const map_location & get_goto() const
The map location to which this unit is moving over multiple turns, if any.
std::string label
What to show in the filter's drop-down list.
std::string id
Text to match against addon_info.tags()
Standard logging facilities (interface).
std::set< std::string > get_recruits(int side, const map_location &recruit_loc)
Gets the recruitable units from a side's leaders' personal recruit lists who can recruit on or from a...
game_events::pump_result_t get_village(const map_location &loc, int side, bool *action_timebonus, bool fire_event)
Makes it so the village at the given location is owned by the given side.
std::vector< unit_const_ptr > get_recalls(int side, const map_location &recall_loc)
Gets the recallable units for a side, restricted by that side's leaders' personal abilities to recall...
std::size_t move_unit_and_record(const std::vector< map_location > &steps, bool continued_move, bool *interrupted)
Wrapper around the other overload.
std::string find_recall_location(const int side, map_location &recall_location, map_location &recall_from, const unit &unit_recall)
Finds a location on which to recall unit_recall.
auto serialize_timestamp(const std::chrono::system_clock::time_point &time)
EXIT_STATUS start(bool clear_id, const std::string &filename, bool take_screenshot, const std::string &screenshot_filename)
Main interface for launching the editor from the title screen.
Handling of system events.
std::string get_legacy_editor_dir()
const std::string map_extension
void write_file(const std::string &fname, const std::string &data, std::ios_base::openmode mode)
Throws io_exception if an error occurs.
const color_t LABEL_COLOR
std::string private_message
Game configuration data as global variables.
bool ignore_replay_errors
const std::string observer_team_name
observer team name used for observer team chat
void set_debug(bool new_debug)
void show_transient_error_message(const std::string &message, const std::string &image, const bool message_use_markup)
Shows a transient error message to the user.
void show_transient_message(const std::string &title, const std::string &message, const std::string &image, const bool message_use_markup, const bool title_use_markup)
Shows a transient message to the user.
void show_message(const std::string &title, const std::string &msg, const std::string &button_caption, const bool auto_close, const bool message_use_markup, const bool title_use_markup)
Shows a message to the user.
retval
Default window/dialog return values.
@ OK
Dialog was closed with the OK button.
@ CANCEL
Dialog was closed with the CANCEL button.
void show_terrain_description(const terrain_type &t)
void show_unit_description(const unit &u)
void show_help(const std::string &show_topic)
Open the help browser.
void flush_cache()
Purges all image caches.
std::string tag(std::string_view tag, Args &&... data)
Wraps the given data in the specified tag.
void send_to_server(const config &data)
Attempts to send given data to server if a connection is open.
bool logged_in_as_moderator()
Gets whether the currently logged-in user is a moderator.
game_events::manager * game_events
bool ci_search(const std::string &s1, const std::string &s2)
Case-insensitive search.
static std::string sgettext(const char *str)
std::string check_recruit_list(const std::string &type, int side_number, const map_location &target_hex)
std::string check_recruit_purse(int unit_cost, int current_purse, int investments)
int planned_gold_spent(int side_number)
std::tuple< std::string, map_location, map_location > validate_recruit_target(const std::string &type, int side_number, const map_location &target_hex)
Verifies that target_hex is a valid recruit location for the given side.
auto find(Container &container, const Value &value, const Projection &projection={})
@ STRIP_SPACES
REMOVE_EMPTY: remove empty elements.
std::string get_unknown_exception_type()
Utility function for finding the type of thing caught with catch(...).
std::map< std::string, t_string > string_map
std::vector< std::string > split(const config_attribute_value &val)
auto * find(Container &container, const Value &value)
Convenience wrapper for using find on a container without needing to comare to end()
static void msg(const char *act, debug_info &i, const char *to="", const char *result="")
std::shared_ptr< const unit > unit_const_ptr
const std::string & gender_string(unit_race::GENDER gender)
static config unit_name(const unit *u)
rect dst
Location on the final composed sheet.
rect src
Non-transparent portion of the surface to compose.
Thrown when a lexical_cast fails.
The basic class for representing 8-bit RGB or RGBA colour values.
An exception object used when an IO error occurs.
Encapsulates the map of the game.
static const map_location & null_location()
Structure which holds a single route and marks for special events.
std::vector< map_location > & steps
Object which contains all the possible locations a unit can move to, with associated best routes to t...
static std::string get_string(enum_type key)
Converts a enum to its string equivalent.
static constexpr utils::optional< enum_type > get_enum(const std::string_view value)
Converts a string into its enum equivalent.
Object which temporarily resets a unit's movement.
ONLY IF whiteboard is currently active, applies the planned unit map for the duration of the struct's...
Applies the planned unit map for the duration of the struct's life.
const std::string & gamedata
static map_location::direction n
unit_type_data unit_types
Various functions that implement the undoing (and redoing) of in-game commands.