84 #define ERR_NG LOG_STREAM(err, log_engine)
85 #define LOG_NG LOG_STREAM(info, log_engine)
153 const auto& unit_dlg = units_dialog::build_unit_list_dialog(
unit_list);
155 if (unit_dlg->show() && unit_dlg->is_selected()) {
191 symbols[
"msg"] =
e.what();
192 const std::string
msg =
VGETTEXT(
"Could not save the map: $msg", symbols);
200 gui2::dialogs::preferences_dialog::display();
208 c[
"name"] =
"prototype of chat log";
220 ?
board().is_observer()
221 ?
_(
"Send to observers only")
222 :
_(
"Send to allies only")
240 if(
board().is_observer()) {
259 std::map<const unit_type*, t_string> err_msgs_map;
260 std::vector<const unit_type*> recruit_list;
262 std::vector<t_string> unknown_units;
265 for(
const auto&
recruit : recruits) {
269 unknown_units.emplace_back(
recruit);
276 if (!err_msg.
empty()) {
277 err_msgs_map[
type] = err_msg;
279 recruit_list.push_back(
type);
282 if(!unknown_units.empty()) {
287 const auto message =
VNGETTEXT(
"Error: there’s an unknown unit type on your recruit list: $unknown_ids",
288 "Error: there are several unknown unit types on your recruit list: $unknown_ids",
289 unknown_units.size(),
294 if(recruit_list.empty()) {
299 const auto& dlg = units_dialog::build_recruit_dialog(recruit_list, err_msgs_map, current_team);
301 if(dlg->show() && dlg->is_selected()) {
302 const auto&
type = recruit_list[dlg->get_selected_index()];
304 do_recruit(
type->id(), side_num, recruit_hex);
308 void menu_handler::repeat_recruit(
int side_num,
const map_location& last_hex)
310 const std::string& last_recruit = board().get_team(side_num).last_recruit();
311 if(!last_recruit.empty()) {
313 do_recruit(last_recruit, side_num, recruit_hex);
317 bool menu_handler::do_recruit(
const std::string& name,
int side_num,
map_location&
loc)
320 team& current_team = board().get_team(side_num);
323 if(res.empty() && (!pc_.get_whiteboard() || !pc_.get_whiteboard()->save_recruit(name, side_num,
loc))) {
330 }
else if(res.empty()) {
341 if(pc_.get_disallow_recall()) {
346 team& current_team = board().get_team(side_num);
348 std::vector<unit_const_ptr> recall_list_team;
354 DBG_WB <<
"menu_handler::recall: Contents of wb-modified recall list:";
361 _(
"There are no troops available to recall.\n(You must have veteran survivors from a previous scenario.)"));
365 if(recall_list_team.empty()) {
370 const auto& dlg = units_dialog::build_recall_dialog(recall_list_team, current_team);
372 if(!dlg->show() || !dlg->is_selected()) {
376 int res = dlg->get_selected_index();
385 if(sel_unit->recall_cost() > -1) {
386 unit_cost = sel_unit->recall_cost();
389 int wb_gold = pc_.get_whiteboard() ? pc_.get_whiteboard()->get_spent_gold_for(side_num) : 0;
391 if(current_team.
gold() - wb_gold < unit_cost) {
393 i18n_symbols[
"cost"] = std::to_string(unit_cost);
394 std::string
msg =
VNGETTEXT(
"You must have at least 1 gold piece to recall a unit.",
395 "You must have at least $cost gold pieces to recall this unit.", unit_cost, i18n_symbols);
400 LOG_NG <<
"recall index: " << res;
417 if(!pc_.get_whiteboard()
418 || !pc_.get_whiteboard()->save_recall(*sel_unit, side_num, recall_location)) {
423 ERR_NG <<
"menu_handler::recall(): Unit does not exist in the recall list.";
429 void menu_handler::show_enemy_moves(
bool ignore_units,
int side_num)
436 gui_->unhighlight_reach();
439 for(
auto& u : pc_.get_units()) {
440 bool invisible = u.invisible(u.get_location());
442 if(board().get_team(side_num).is_enemy(u.side()) && !gui_->fogged(u.get_location()) && !u.incapacitated()
446 =
pathfind::paths(u,
false,
true, gui_->viewing_team(), 0,
false, ignore_units);
448 gui_->highlight_another_reach(
path, hex_under_mouse);
452 gui_->invalidate(u.get_location());
457 const bool selected_hex_has_unit = mh.
hex_hosts_unit(hex_under_mouse);
459 if(selected_hex_has_unit) {
468 void menu_handler::toggle_shroud_updates(
int side_num)
470 team& current_team = board().get_team(side_num);
474 update_shroud_now(side_num);
481 void menu_handler::update_shroud_now(
int )
490 bool units_alive(
int side_num,
const unit_map& units)
492 for(
auto&
unit : units) {
501 bool partmoved_units(
502 int side_num,
const unit_map& units,
const game_board& board,
const std::shared_ptr<wb::manager>& whiteb)
504 for(
auto&
unit : units) {
519 int side_num,
const unit_map& units,
const game_board& board,
const std::shared_ptr<wb::manager>& whiteb)
521 for(
auto&
unit : units) {
524 && (!whiteb || !whiteb->unit_has_actions(&
unit))) {
534 bool menu_handler::end_turn(
int side_num)
539 reason =
_(
"You cannot end your turn yet!");
545 std::size_t team_num =
static_cast<std::size_t
>(side_num - 1);
546 if(team_num < pc_.get_teams().size() && pc_.get_teams()[team_num].no_turn_confirmation()) {
551 && (!pc_.get_whiteboard() || !pc_.get_whiteboard()->current_side_has_actions())
552 && units_alive(side_num, pc_.get_units())) {
554 _(
"You have not started your turn yet. Do you really want to end your turn?"),
555 message::yes_no_buttons);
561 else if(
prefs::get().yellow_confirm() && partmoved_units(side_num, pc_.get_units(), board(), pc_.get_whiteboard())) {
563 _(
"Some units have movement left. Do you really want to end your turn?"),
564 message::yes_no_buttons);
570 else if(
prefs::get().green_confirm() && unmoved_units(side_num, pc_.get_units(), board(), pc_.get_whiteboard())) {
572 _(
"Some units have not moved. Do you really want to end your turn?"),
573 message::yes_no_buttons);
581 if(pc_.get_whiteboard() && !pc_.get_whiteboard()->allow_end_turn()) {
588 void menu_handler::goto_leader(
int side_num)
591 if(
i != pc_.get_units().end() &&
i->is_visible_to_team(gui_->viewing_team(),
false)) {
596 void menu_handler::unit_description()
599 if(un != pc_.get_units().end()) {
607 if(pc_.get_map().on_board(
loc) ==
false || gui_->shrouded(
loc)) {
616 void menu_handler::rename_unit()
619 if(un == pc_.get_units().end() || gui_->viewing_team().side() != un->side()) {
623 if(un->unrenamable()) {
627 std::string name = un->name();
628 const std::string title(
_(
"Rename Unit"));
629 const std::string
label(
_(
"Name:"));
631 if(edit_text::execute(title,
label, name)) {
634 gui_->invalidate_unit();
640 const mouse_handler& mousehandler = pc_.get_mouse_handler_base();
641 const bool see_all = gui_->show_everything() || (pc_.is_replay() && pc_.get_replay_controller()->see_all());
644 if(res != pc_.get_units().end()) {
655 typedef std::tuple<const unit_type*, unit_race::GENDER, std::string> type_gender_variation;
664 type_gender_variation choose_unit()
667 const auto& create_dlg = units_dialog::build_create_dialog(types_list);
669 if (!create_dlg->show() || !create_dlg->is_selected()) {
670 ERR_NG <<
"Create unit dialog returned nonexistent or unusable unit_type id.";
674 const unit_type* ut = types_list[create_dlg->get_selected_index()];
677 return type_gender_variation(ut, gender, create_dlg->variation());
684 void create_and_place(
691 const std::string& variation =
"")
699 "variation", variation,
714 assert(gui_ !=
nullptr);
717 if(
const auto& [
type, gender, variation] = choose_unit();
type !=
nullptr) {
719 create_and_place(*gui_, pc_.get_map(), pc_.get_units(), destination, *
type, gender, variation);
727 if(
i == pc_.get_units().end()) {
728 if(!pc_.get_map().is_village(
loc)) {
736 if(
team >
static_cast<int>(pc_.get_teams().size())) {
741 int side =
i->side();
743 if(side >
static_cast<int>(pc_.get_teams().size())) {
748 if(pc_.get_map().is_village(
loc)) {
760 void menu_handler::label_terrain(
mouse_handler& mousehandler,
bool team_only)
763 if(pc_.get_map().on_board(
loc) ==
false) {
768 std::string
label = old_label ? old_label->
text() :
"";
770 if(edit_label::execute(
label, team_only)) {
771 std::string team_name;
775 team_name = gui_->labels().team_name();
779 const terrain_label* res = gui_->labels().set_label(
loc,
label, gui_->viewing_team_index(), team_name, color);
786 void menu_handler::clear_labels()
788 if(!board().is_observer()) {
791 _(
"Are you sure you want to clear map labels?"),
792 message::yes_no_buttons
796 std::string viewing_team = gui_->viewing_team().team_name();
797 gui_->labels().clear(viewing_team,
false);
803 void menu_handler::label_settings()
805 if(label_settings::execute(board())) {
806 gui_->labels().recalculate_labels();
813 if(
i == pc_.get_units().end() || !
i->move_interrupted()) {
815 if(
i == pc_.get_units().end() || !
i->move_interrupted()) {
819 move_unit_to_loc(
i,
i->get_interrupted_move(),
true, side_num, mousehandler);
822 void menu_handler::move_unit_to_loc(
829 assert(ui != pc_.get_units().end());
833 if(route.
steps.empty()) {
837 assert(route.
steps.front() == ui->get_location());
839 gui_->set_route(&route);
840 gui_->unhighlight_reach();
843 LOG_NG <<
"move_unit_to_loc " << route.
steps.front() <<
" to " << route.
steps.back();
848 gui_->set_route(
nullptr);
849 gui_->invalidate_game_status();
858 bool wait_blocker_move =
true;
859 std::set<map_location> fully_moved;
862 bool blocked_unit =
false;
865 blocked_unit =
false;
866 for(
auto&
unit : pc_.get_units()) {
874 if(goto_loc == current_loc) {
879 if(!pc_.get_map().on_board(goto_loc)) {
884 if(fully_moved.count(current_loc)) {
890 if(route.
steps.size() <= 1) {
891 fully_moved.insert(current_loc);
897 pathfind::marked_route::mark_map::const_iterator
w = route.
marks.begin();
898 for(;
w != route.
marks.end(); ++
w) {
899 if(
w->second.turns == 1) {
900 next_stop =
w->first;
905 if(next_stop == current_loc) {
906 fully_moved.insert(current_loc);
912 if(pc_.get_units().count(next_stop)) {
914 if(wait_blocker_move)
918 gui_->set_route(&route);
921 LOG_NG <<
"execute goto from " << route.
steps.front() <<
" to " << route.
steps.back();
928 wait_blocker_move =
true;
932 if(!change && wait_blocker_move) {
934 wait_blocker_move =
false;
937 }
while(change && blocked_unit);
940 gui_->set_route(
nullptr);
941 gui_->invalidate_game_status();
944 void menu_handler::toggle_ellipses()
947 gui_->invalidate_all();
950 void menu_handler::toggle_grid()
953 gui_->invalidate_all();
956 void menu_handler::unit_hold_position(
mouse_handler& mousehandler,
int side_num)
959 if(un != pc_.get_units().end() && un->side() == side_num && un->movement_left() >= 0) {
960 un->toggle_hold_position();
965 if(un->hold_position()) {
974 if(un != pc_.get_units().end() && un->side() == side_num && un->movement_left() >= 0) {
975 un->toggle_user_end_turn();
980 if(un->user_end_turn()) {
992 void menu_handler::search()
994 std::ostringstream
msg;
996 if(last_search_hit_.valid()) {
997 msg <<
" [" << last_search_ <<
"]";
1003 void menu_handler::do_speak()
1007 chat_handler::do_speak(
1008 textbox_info_.box()->text(), textbox_info_.check() !=
nullptr ? textbox_info_.check()->checked() :
false);
1011 void menu_handler::add_chat_message(
const std::time_t& time,
1012 const std::string& speaker,
1017 gui_->get_chat_manager().add_chat_message(time, speaker, side,
message,
type,
false);
1044 using chmap::get_commands_list;
1045 using chmap::command_failed;
1051 chat_command_handler::command_handler
h,
1052 const std::string&
help =
"",
1053 const std::string& usage =
"",
1054 const std::string& flags =
"")
1056 chmap::register_command(cmd,
h,
help, usage, flags +
"N");
1061 chmap::register_alias(to_cmd, cmd);
1066 return chmap::get_arg(
i);
1071 return chmap::get_cmd();
1076 return chmap::get_data(
n);
1080 using chmap::register_command;
1081 using chmap::register_alias;
1083 using chmap::is_enabled;
1084 using chmap::command_failed_need_arg;
1092 void do_controller();
1094 void do_foreground();
1097 void do_benchmark();
1099 void do_save_quit();
1101 void do_ignore_replay_errors();
1103 void do_next_level();
1104 void do_choose_level();
1106 void do_turn_limit();
1110 void do_unsafe_lua();
1112 void do_set_alias();
1116 void do_control_dialog();
1121 void do_undiscover();
1127 void do_toggle_draw_coordinates();
1128 void do_toggle_draw_terrain_codes();
1129 void do_toggle_draw_num_of_bitmaps();
1130 void do_toggle_whiteboard();
1131 void do_whiteboard_options();
1135 return _(
"(D) — debug only, (N) — network only, (A) — admin only");
1138 using chat_command_handler::get_command_flags_description;
1141 std::string space(
" ");
1142 return (
c.has_flag(
'D') ? space +
_(
"(debug command)") :
"")
1143 + (
c.has_flag(
'N') ? space +
_(
"(network only)") :
"")
1144 + (
c.has_flag(
'A') ? space +
_(
"(admin only)") :
"")
1145 + (
c.has_flag(
'S') ? space +
_(
"(not during other events)") :
"");
1148 using map::is_enabled;
1152 || (
c.has_flag(
'N') && !menu_handler_.pc_.is_networked_mp())
1159 menu_handler_.add_chat_message(std::time(
nullptr), title, 0,
message);
1164 chat_command_handler::init_map();
1166 chmap::get_command(
"log")->flags =
"";
1167 chmap::get_command(
"version")->flags =
"";
1168 chmap::get_command(
"ignore")->flags =
"";
1169 chmap::get_command(
"friend")->flags =
"";
1170 chmap::get_command(
"remove")->flags =
"";
1172 chmap::set_cmd_prefix(
":");
1173 chmap::set_cmd_flag(
true);
1175 register_command(
"refresh", &console_handler::do_refresh,
_(
"Refresh gui."));
1176 register_command(
"droid", &console_handler::do_droid,
_(
"Switch a side to/from AI control."),
1180 _(
"[<side> [on/off/full]]\n“on” = enable but retain vision, “full” = as if it’s controlled by another player"));
1181 register_command(
"terrain", &console_handler::do_terrain,
_(
"Change terrain type of current hex"),
1183 _(
"<terrain type> [both|base|overlay]"),
"DS");
1184 register_command(
"idle", &console_handler::do_idle,
_(
"Switch a side to/from idle state."),
1188 _(
"command_idle^[<side> [on/off]]"));
1189 register_command(
"theme", &console_handler::do_theme,
_(
"Change the in-game theme."));
1190 register_command(
"control", &console_handler::do_control,
1191 _(
"Assign control of a side to a different player or observer."),
_(
"<side> <nickname>"),
"N");
1192 register_command(
"controller", &console_handler::do_controller,
_(
"Query the controller status of a side."),
1194 register_command(
"clear", &console_handler::do_clear,
_(
"Clear chat history."));
1195 register_command(
"foreground", &console_handler::do_foreground,
_(
"Debug foreground terrain."),
"",
"D");
1197 "layers", &console_handler::do_layers,
_(
"Debug layers from terrain under the mouse."),
"",
"D");
1198 register_command(
"fps", &console_handler::do_fps,
_(
"Display and log fps (Frames Per Second)."));
1199 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."));
1200 register_command(
"save", &console_handler::do_save,
_(
"Save game."));
1201 register_alias(
"save",
"w");
1202 register_command(
"quit", &console_handler::do_quit,
_(
"Quit game."));
1204 register_alias(
"quit",
"q!");
1205 register_command(
"save_quit", &console_handler::do_save_quit,
_(
"Save and quit."));
1206 register_alias(
"save_quit",
"wq");
1207 register_command(
"ignore_replay_errors", &console_handler::do_ignore_replay_errors,
_(
"Ignore replay errors."));
1208 register_command(
"nosaves", &console_handler::do_nosaves,
_(
"Disable autosaves."));
1209 register_command(
"next_level", &console_handler::do_next_level,
1210 _(
"Advance to the next scenario, or scenario identified by ‘id’"),
_(
"<id>"),
"DS");
1211 register_alias(
"next_level",
"n");
1212 register_command(
"choose_level", &console_handler::do_choose_level,
_(
"Choose next scenario"),
"",
"DS");
1213 register_alias(
"choose_level",
"cl");
1214 register_command(
"turn", &console_handler::do_turn,
1215 _(
"Change turn number (and time of day), or increase by one if no number is specified."),
_(
"[turn]"),
1217 register_command(
"turn_limit", &console_handler::do_turn_limit,
1218 _(
"Change turn limit, or turn the turn limit off if no number is specified or it’s −1."),
_(
"[limit]"),
1220 register_command(
"debug", &console_handler::do_debug,
_(
"Turn debug mode on."));
1221 register_command(
"nodebug", &console_handler::do_nodebug,
_(
"Turn debug mode off."),
"",
"D");
1223 "lua", &console_handler::do_lua,
_(
"Execute a Lua statement."),
_(
"<command>[;<command>...]"),
"DS");
1225 "unsafe_lua", &console_handler::do_unsafe_lua,
_(
"Grant higher privileges to Lua scripts."),
"",
"D");
1226 register_command(
"custom", &console_handler::do_custom,
_(
"Set the command used by the custom command hotkey"),
1227 _(
"<command>[;<command>...]"));
1228 register_command(
"give_control", &console_handler::do_control_dialog,
1229 _(
"Invoke a dialog allowing changing control of MP sides."),
"",
"N");
1230 register_command(
"inspect", &console_handler::do_inspect,
_(
"Launch the gamestate inspector"),
"",
"D");
1232 "alias", &console_handler::do_set_alias,
_(
"Set or show alias to a command"),
_(
"<name>[=<command>]"));
1234 "set_var", &console_handler::do_set_var,
_(
"Set a scenario variable."),
_(
"<var>=<value>"),
"DS");
1235 register_command(
"show_var", &console_handler::do_show_var,
_(
"Show a scenario variable."),
_(
"<var>"),
"D");
1236 register_command(
"unit", &console_handler::do_unit,
1238 _(
"Modify a unit variable. (Only top level keys are supported, and advances=<number>.)"),
1239 _(
"<var>=<value>"),
"DS");
1245 register_command(
"discover", &console_handler::do_discover,
_(
"Discover all units in help."),
"");
1246 register_command(
"undiscover", &console_handler::do_undiscover,
_(
"‘Undiscover’ all units in help."),
"");
1247 register_command(
"create", &console_handler::do_create,
_(
"Create a unit."),
_(
"<unit type id>"),
"DS");
1248 register_command(
"fog", &console_handler::do_fog,
_(
"Toggle fog for the current player."),
"",
"DS");
1249 register_command(
"shroud", &console_handler::do_shroud,
_(
"Toggle shroud for the current player."),
"",
"DS");
1250 register_command(
"gold", &console_handler::do_gold,
_(
"Give gold to the current player."),
_(
"<amount>"),
"DS");
1251 register_command(
"throw", &console_handler::do_event,
_(
"Fire a game event."),
_(
"<event name>"),
"DS");
1252 register_alias(
"throw",
"fire");
1253 register_command(
"show_coordinates", &console_handler::do_toggle_draw_coordinates,
1254 _(
"Toggle overlaying of x,y coordinates on hexes."));
1255 register_alias(
"show_coordinates",
"sc");
1256 register_command(
"show_terrain_codes", &console_handler::do_toggle_draw_terrain_codes,
1257 _(
"Toggle overlaying of terrain codes on hexes."));
1258 register_alias(
"show_terrain_codes",
"tc");
1259 register_command(
"show_num_of_bitmaps", &console_handler::do_toggle_draw_num_of_bitmaps,
1260 _(
"Toggle overlaying of number of bitmaps on hexes."));
1261 register_alias(
"show_num_of_bitmaps",
"bn");
1262 register_command(
"whiteboard", &console_handler::do_toggle_whiteboard,
_(
"Toggle planning mode."));
1263 register_alias(
"whiteboard",
"wb");
1265 "whiteboard_options", &console_handler::do_whiteboard_options,
_(
"Access whiteboard options dialog."));
1266 register_alias(
"whiteboard_options",
"wbo");
1268 if(
auto alias_list =
prefs::get().get_alias()) {
1269 for(
const auto& [key, value] : alias_list->attribute_range()) {
1270 register_alias(value, key);
1280 void menu_handler::send_chat_message(
const std::string&
message,
bool allies_only)
1285 auto now = std::chrono::system_clock::now();
1288 const int side = board().
is_observer() ? 0 : gui_->viewing_team().side();
1289 if(!board().is_observer()) {
1296 if(board().is_observer()) {
1299 cfg[
"to_sides"] = gui_->viewing_team().allied_human_teams();
1305 auto as_time_t = std::chrono::system_clock::to_time_t(now);
1306 add_chat_message(as_time_t, cfg[
"id"], side,
message,
1310 void menu_handler::do_search(
const std::string& new_search)
1312 if(new_search.empty() ==
false && new_search != last_search_)
1313 last_search_ = new_search;
1315 if(last_search_.empty())
1321 std::vector<std::string> args =
utils::split(last_search_,
',');
1322 if(args.size() == 2) {
1324 x = lexical_cast_default<int>(args[0], 0) - 1;
1325 y = lexical_cast_default<int>(args[1], 0) - 1;
1326 if(x >= 0 && x < pc_.get_map().w() && y >= 0 && y < pc_.get_map().h()) {
1339 loc.
x = (
loc.
x + 1) % pc_.get_map().w();
1341 loc.
y = (
loc.
y + 1) % pc_.get_map().h();
1344 if(!gui_->shrouded(
loc)) {
1347 const std::string& label_text =
label->text().str();
1353 if(!gui_->fogged(
loc)) {
1355 if(ui != pc_.get_units().end()) {
1356 const std::string&
unit_name = ui->name();
1358 if(!gui_->viewing_team().is_enemy(ui->side())
1359 || !ui->invisible(ui->get_location())) {
1371 last_search_hit_ =
loc;
1373 gui_->highlight_hex(
loc);
1378 symbols[
"search"] = last_search_;
1379 const std::string
msg =
VGETTEXT(
"Could not find label or unit "
1380 "containing the string ‘$search’.",
1386 void menu_handler::do_command(
const std::string& str)
1392 std::vector<std::string> menu_handler::get_commands_list()
1403 void console_handler::do_refresh()
1408 menu_handler_.gui_->create_buttons();
1409 menu_handler_.gui_->queue_rerender();
1412 void console_handler::do_droid()
1415 const std::string side_s = get_arg(1);
1416 std::string action = get_arg(2);
1417 std::transform(action.begin(), action.end(), action.begin(), tolower);
1419 const unsigned int side = side_s.empty() ? team_num_ : lexical_cast_default<unsigned int>(side_s);
1420 const bool is_your_turn = menu_handler_.pc_.current_side() ==
static_cast<int>(menu_handler_.gui_->viewing_team().side());
1423 symbols[
"side"] = std::to_string(side);
1425 if(side < 1 || side > menu_handler_.pc_.get_teams().size()) {
1426 command_failed(
VGETTEXT(
"Can’t droid invalid side: ‘$side’.", symbols));
1428 }
else if(menu_handler_.board().get_team(side).is_network()) {
1429 command_failed(
VGETTEXT(
"Can’t droid networked side: ‘$side’.", symbols));
1431 }
else if(menu_handler_.board().get_team(side).is_local()) {
1432 bool changed =
false;
1434 const bool is_human = menu_handler_.board().get_team(side).is_human();
1435 const bool is_droid = menu_handler_.board().get_team(side).is_droid();
1436 const bool is_proxy_human = menu_handler_.board().get_team(side).is_proxy_human();
1437 const bool is_ai = menu_handler_.board().get_team(side).is_ai();
1439 if(action ==
"on") {
1440 if(is_ai && !is_your_turn) {
1441 command_failed(
_(
"It is not allowed to change a side from AI to human control when it’s not your turn."));
1444 if(!is_human || !is_droid) {
1445 menu_handler_.board().get_team(side).make_human();
1446 menu_handler_.board().get_team(side).make_droid();
1449 menu_handler_.pc_.send_to_wesnothd(
config {
"change_controller",
config {
"side", side,
"player",
prefs::get().
login(),
"to", side_controller::human}});
1451 print(get_cmd(),
VGETTEXT(
"Side ‘$side’ controller is now controlled by: AI.", symbols));
1453 print(get_cmd(),
VGETTEXT(
"Side ‘$side’ is already droided.", symbols));
1455 }
else if(action ==
"off") {
1456 if(is_ai && !is_your_turn) {
1457 command_failed(
_(
"It is not allowed to change a side from AI to human control when it’s not your turn."));
1460 if(!is_human || !is_proxy_human) {
1461 menu_handler_.board().get_team(side).make_human();
1462 menu_handler_.board().get_team(side).make_proxy_human();
1465 menu_handler_.pc_.send_to_wesnothd(
config {
"change_controller",
config {
"side", side,
"player",
prefs::get().
login(),
"to", side_controller::human}});
1467 print(get_cmd(),
VGETTEXT(
"Side ‘$side’ controller is now controlled by: human.", symbols));
1469 print(get_cmd(),
VGETTEXT(
"Side ‘$side’ is already not droided.", symbols));
1471 }
else if(action ==
"full") {
1473 command_failed(
_(
"It is not allowed to change a side from human to AI control when it’s not your turn."));
1476 if(!is_ai || !is_droid) {
1477 menu_handler_.board().get_team(side).make_ai();
1478 menu_handler_.board().get_team(side).make_droid();
1480 if(is_human || is_proxy_human) {
1481 menu_handler_.pc_.send_to_wesnothd(
config {
"change_controller",
config {
"side", side,
"player",
prefs::get().
login(),
"to", side_controller::ai}});
1483 print(get_cmd(),
VGETTEXT(
"Side ‘$side’ controller is now fully controlled by: AI.", symbols));
1485 print(get_cmd(),
VGETTEXT(
"Side ‘$side’ is already fully AI controlled.", symbols));
1487 }
else if(action ==
"") {
1488 if(is_ai && !is_your_turn) {
1489 command_failed(
_(
"It is not allowed to change a side from AI to human control when it’s not your turn."));
1492 if(is_ai || is_droid) {
1493 menu_handler_.board().get_team(side).make_human();
1494 menu_handler_.board().get_team(side).make_proxy_human();
1497 menu_handler_.pc_.send_to_wesnothd(
config {
"change_controller",
config {
"side", side,
"player",
prefs::get().
login(),
"to", side_controller::human}});
1499 print(get_cmd(),
VGETTEXT(
"Side ‘$side’ controller is now controlled by: human.", symbols));
1501 menu_handler_.board().get_team(side).make_human();
1502 menu_handler_.board().get_team(side).make_droid();
1505 menu_handler_.pc_.send_to_wesnothd(
config {
"change_controller",
config {
"side", side,
"player",
prefs::get().
login(),
"to", side_controller::human}});
1507 print(get_cmd(),
VGETTEXT(
"Side ‘$side’ controller is now controlled by: AI.", symbols));
1510 print(get_cmd(),
VGETTEXT(
"Invalid action provided for side ‘$side’. Valid actions are: on, off, full.", symbols));
1513 if(team_num_ == side && changed) {
1515 psc->set_player_type_changed();
1519 command_failed(
VGETTEXT(
"Side ‘$side’ is not a human or AI player.", symbols));
1522 menu_handler_.textbox_info_.close();
1525 void console_handler::do_terrain()
1529 const std::string mode_str = get_arg(2);
1539 "mode_str", mode_str,
1544 void console_handler::do_idle()
1547 const std::string side_s = get_arg(1);
1548 const std::string action = get_arg(2);
1550 const unsigned int side = side_s.empty() ? team_num_ : lexical_cast_default<unsigned int>(side_s);
1552 if(side < 1 || side > menu_handler_.pc_.get_teams().size()) {
1554 symbols[
"side"] = side_s;
1555 command_failed(
VGETTEXT(
"Can’t idle invalid side: ‘$side’.", symbols));
1557 }
else if(menu_handler_.board().get_team(side).is_network()) {
1559 symbols[
"side"] = std::to_string(side);
1560 command_failed(
VGETTEXT(
"Can’t idle networked side: ‘$side’.", symbols));
1562 }
else if(menu_handler_.board().get_team(side).is_local_ai()) {
1564 symbols[
"side"] = std::to_string(side);
1565 command_failed(
VGETTEXT(
"Can’t idle local ai side: ‘$side’.", symbols));
1567 }
else if(menu_handler_.board().get_team(side).is_local_human()) {
1568 if(menu_handler_.board().get_team(side).is_idle() ? action ==
" on" : action ==
" off") {
1572 menu_handler_.board().get_team(side).toggle_idle();
1573 if(team_num_ == side) {
1575 psc->set_player_type_changed();
1579 menu_handler_.textbox_info_.close();
1582 void console_handler::do_theme()
1596 return t.save_id() == save_id_;
1602 void console_handler::do_control()
1605 if(!menu_handler_.pc_.is_networked_mp()) {
1609 const std::string side = get_arg(1);
1610 const std::string player = get_arg(2);
1611 if(player.empty()) {
1612 command_failed_need_arg(2);
1616 unsigned int side_num;
1618 side_num = lexical_cast<unsigned int>(side);
1620 const auto& teams = menu_handler_.pc_.get_teams();
1621 const auto it_t = std::find_if(teams.begin(), teams.end(),
save_id_matches(side));
1623 if(it_t == teams.end()) {
1625 symbols[
"side"] = side;
1626 command_failed(
VGETTEXT(
"Can’t change control of invalid side: ‘$side’.", symbols));
1629 side_num = it_t->side();
1633 if(side_num < 1 || side_num > menu_handler_.pc_.get_teams().size()) {
1635 symbols[
"side"] = side;
1636 command_failed(
VGETTEXT(
"Can’t change control of out-of-bounds side: ‘$side’.", symbols));
1640 menu_handler_.request_control_change(side_num, player);
1641 menu_handler_.textbox_info_.close();
1644 void console_handler::do_controller()
1646 const std::string side = get_arg(1);
1647 unsigned int side_num;
1649 side_num = lexical_cast<unsigned int>(side);
1652 symbols[
"side"] = side;
1653 command_failed(
VGETTEXT(
"Can’t query control of invalid side: ‘$side’.", symbols));
1657 if(side_num < 1 || side_num > menu_handler_.pc_.get_teams().size()) {
1659 symbols[
"side"] = side;
1660 command_failed(
VGETTEXT(
"Can’t query control of out-of-bounds side: ‘$side’.", symbols));
1665 if(!menu_handler_.board().get_team(side_num).is_proxy_human()) {
1669 if(menu_handler_.board().get_team(side_num).is_network()) {
1670 report +=
" (networked)";
1673 print(get_cmd(), report);
1676 void console_handler::do_clear()
1678 menu_handler_.gui_->get_chat_manager().clear_chat_messages();
1681 void console_handler::do_foreground()
1684 menu_handler_.gui_->invalidate_all();
1687 void console_handler::do_layers()
1689 display& disp = *(menu_handler_.gui_);
1703 if(menu_handler_.pc_.get_map().on_board_with_border(
loc)) {
1704 terrain_layers::display(disp,
loc);
1708 void console_handler::do_fps()
1713 void console_handler::do_benchmark()
1718 void console_handler::do_save()
1720 menu_handler_.pc_.do_consolesave(get_data());
1723 void console_handler::do_save_quit()
1729 void console_handler::do_quit()
1734 void console_handler::do_ignore_replay_errors()
1739 void console_handler::do_nosaves()
1744 void console_handler::do_next_level()
1749 void console_handler::do_choose_level()
1751 std::string
tag = menu_handler_.pc_.get_classification().get_tagname();
1752 std::vector<std::string> options;
1754 if(
tag !=
"multiplayer") {
1756 const std::string&
id = sc[
"id"];
1757 options.push_back(
id);
1758 if(
id == menu_handler_.gamedata().next_scenario()) {
1765 std::string scenario_id = menu_handler_.pc_.get_mp_settings().mp_scenario;
1766 if(
auto this_scenario = menu_handler_.game_config_.find_child(
tag,
"id", scenario_id)) {
1767 std::string addon_id = this_scenario[
"addon_id"].str();
1769 if(sc[
"addon_id"] == addon_id) {
1770 std::string
id = sc[
"id"];
1771 options.push_back(
id);
1772 if(
id == menu_handler_.gamedata().next_scenario()) {
1779 std::sort(options.begin(), options.end());
1780 int choice = std::distance(options.begin(), std::lower_bound(options.begin(), options.end(), next));
1792 if(std::size_t(choice) < options.size()) {
1797 void console_handler::do_turn()
1799 tod_manager& tod_man = menu_handler_.gamestate().tod_manager_;
1801 int turn = tod_man.
turn() + 1;
1802 const std::string&
data = get_data();
1804 turn = lexical_cast_default<int>(
data, 1);
1809 void console_handler::do_turn_limit()
1811 int limit = get_data().empty() ? -1 : lexical_cast_default<int>(get_data(), 1);
1815 void console_handler::do_debug()
1818 print(get_cmd(),
_(
"Debug mode activated!"));
1821 command_failed(
_(
"Debug mode not available in network games"));
1825 void console_handler::do_nodebug()
1828 print(get_cmd(),
_(
"Debug mode deactivated!"));
1833 void console_handler::do_lua()
1835 if(!menu_handler_.gamestate().lua_kernel_) {
1842 void console_handler::do_unsafe_lua()
1844 if(!menu_handler_.gamestate().lua_kernel_) {
1849 _(
"Executing Lua code in in this manner opens your computer to potential security breaches from any "
1850 "malicious add-ons or other programs you may have installed.\n\n"
1851 "Do not continue unless you really know what you are doing."), message::ok_cancel_buttons);
1854 print(get_cmd(),
_(
"Unsafe mode enabled!"));
1855 menu_handler_.gamestate().lua_kernel_->load_package();
1859 void console_handler::do_custom()
1864 void console_handler::do_set_alias()
1866 const std::string
data = get_data();
1868 const std::string alias(
data.begin(), j);
1869 if(j !=
data.end()) {
1870 const std::string command(j + 1,
data.end());
1871 if(!command.empty()) {
1872 register_alias(command, alias);
1876 register_alias(alias, alias);
1884 const std::string command = chmap::get_actual_cmd(alias);
1885 print(get_cmd(),
"'" + alias +
"'" +
" = " +
"'" + command +
"'");
1889 void console_handler::do_set_var()
1891 const std::string
data = get_data();
1893 command_failed_need_arg(1);
1898 if(j !=
data.end()) {
1899 const std::string name(
data.begin(), j);
1900 const std::string value(j + 1,
data.end());
1903 command_failed(
_(
"Variable not found"));
1907 void console_handler::do_show_var()
1912 void console_handler::do_inspect()
1915 gamestate_inspector::display(
1919 void console_handler::do_control_dialog()
1921 mp_change_control::display(menu_handler_);
1924 void console_handler::do_unit()
1932 if(
i == menu_handler_.pc_.get_units().end()) {
1934 symbols[
"unit"] = get_arg(1);
1936 "Debug command ‘unit: $unit’ failed: no unit selected or hovered over.",
1942 const std::string
data = get_data(1);
1944 if(parameters.size() < 2) {
1948 if(parameters[0] ==
"alignment") {
1952 symbols[
"alignment"] = get_arg(1);
1954 "Invalid alignment: ‘$alignment’, needs to be one of lawful, neutral, chaotic, or liminal.",
1964 "name", parameters[0],
1965 "value", parameters[1],
1970 void console_handler::do_discover()
1972 for(
const unit_type_data::unit_type_map::value_type&
i :
unit_types.
types()) {
1977 void console_handler::do_undiscover()
1980 _(
"Do you wish to clear all of your discovered units from help?"), message::yes_no_buttons);
1987 void console_handler::do_create()
1991 if(menu_handler_.pc_.get_map().on_board(
loc)) {
1994 command_failed(
_(
"Invalid unit type"));
1999 create_and_place(*menu_handler_.gui_, menu_handler_.pc_.get_map(), menu_handler_.pc_.get_units(),
loc, *ut);
2001 command_failed(
_(
"Invalid location"));
2005 void console_handler::do_fog()
2010 void console_handler::do_shroud()
2015 void console_handler::do_gold()
2020 void console_handler::do_event()
2025 void console_handler::do_toggle_draw_coordinates()
2028 menu_handler_.gui_->invalidate_all();
2030 void console_handler::do_toggle_draw_terrain_codes()
2033 menu_handler_.gui_->invalidate_all();
2036 void console_handler::do_toggle_draw_num_of_bitmaps()
2039 menu_handler_.gui_->invalidate_all();
2042 void console_handler::do_toggle_whiteboard()
2044 if(
const std::shared_ptr<wb::manager>& whiteb = menu_handler_.pc_.get_whiteboard()) {
2045 whiteb->set_active(!whiteb->is_active());
2046 if(whiteb->is_active()) {
2047 print(get_cmd(),
_(
"Planning mode activated!"));
2048 whiteb->print_help_once();
2050 print(get_cmd(),
_(
"Planning mode deactivated!"));
2055 void console_handler::do_whiteboard_options()
2057 if(menu_handler_.pc_.get_whiteboard()) {
2058 menu_handler_.pc_.get_whiteboard()->options_dlg();
2062 void menu_handler::do_ai_formula(
const std::string& str,
int side_num,
mouse_handler& )
2072 void menu_handler::user_command()
2077 void menu_handler::request_control_change(
int side_num,
const std::string& player)
2079 std::string side = std::to_string(side_num);
2080 if(board().get_team(side_num).is_local_human() && player ==
prefs::get().login()) {
2086 pc_.send_to_wesnothd(
config {
"change_controller",
config {
"side", side,
"player", player}});
2090 void menu_handler::custom_command()
2093 do_command(command);
2097 void menu_handler::ai_formula()
2099 if(!pc_.is_networked_mp()) {
2104 void menu_handler::clear_messages()
2106 gui_->get_chat_manager().clear_chat_messages();
2111 pc_.send_to_wesnothd(cfg);
Various functions related to moving units.
Managing the AIs lifecycle - headers TODO: Refactor history handling and internal commands.
static manager & get_singleton()
A config object defines a single node in a WML file, with access to child nodes.
child_itors child_range(config_key_type 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_
std::vector< std::string > get_commands_list() const
void dispatch(std::string cmd)
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.
Encapsulates the map of the game.
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_auto_shroud(bool turned_on)
Records that the player has toggled automatic shroud updates.
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.
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).
void set_action_bonus_count(const int count)
bool auto_shroud_updates() const
const std::string & team_name() const
int action_bonus_count() const
static color_t get_side_color(int side)
recall_list_manager & recall_list()
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()
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).
const 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_help(const std::string &show_topic)
Open the help browser, show topic with id show_topic.
void show_terrain_description(const terrain_type &t)
void show_unit_description(const unit &u)
void flush_cache()
Purges all image caches.
std::string tag(std::string_view tag, Args &&... data)
Wraps the given data in the specified formatting 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)
static std::string sgettext(const char *str)
t_string recruit_message(const std::string &type_id, map_location &target_hex, map_location &recruited_from, team ¤t_team)
@ 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::string format_conjunct_list(const t_string &empty, const std::vector< t_string > &elems)
Format a conjunctive list.
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)
Thrown when a lexical_cast fails.
The basic class for representing 8-bit RGB or RGBA colour values.
save_id_matches(const std::string &save_id)
bool operator()(const team &t) const
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.