diff --git a/data/core/_main.cfg b/data/core/_main.cfg
index b5bfd270695..18ffefc113b 100644
--- a/data/core/_main.cfg
+++ b/data/core/_main.cfg
@@ -9,6 +9,7 @@ wesnoth.dofile 'lua/wml-tags.lua'
wesnoth.dofile 'lua/feeding.lua'
wesnoth.dofile 'lua/diversion.lua'
wesnoth.dofile 'lua/stun.lua'
+wesnoth.dofile 'lua/carryover_gold.lua'
>>
[/lua]
diff --git a/data/lua/carryover_gold.lua b/data/lua/carryover_gold.lua
new file mode 100644
index 00000000000..00b8683fd7f
--- /dev/null
+++ b/data/lua/carryover_gold.lua
@@ -0,0 +1,147 @@
+local _ = wesnoth.textdomain "wesnoth"
+
+local function get_is_observer()
+ for _, side in ipairs(wesnoth.sides) do
+ if side.controller == "human" and side.is_local then
+ return false
+ end
+ end
+ return true
+end
+
+local function get_num_persistent_teams()
+ local res = 0
+ for _, side in ipairs(wesnoth.sides) do
+ if side.persistent then
+ res = res + 1
+ end
+ end
+ return res
+end
+
+local function get_num_villages()
+ return #(wesnoth.map.find{ gives_income = true })
+end
+
+local function half_signed_value(num)
+ return tostring(num)
+end
+
+local function get_popup_text_basic()
+
+ local is_observer = get_is_observer()
+ local is_victory = wesnoth.scenario.end_level_data.is_victory
+
+ local report = ""
+ local title = ""
+
+ if is_observer then
+ title = _("Scenario Report")
+ elseif is_victory then
+ title = _("Victory")
+ report = report .. "" .. _("You have emerged victorious!") .. ""
+ else
+ title = _("Defeat")
+ report = report .. _("You have been defeated!")
+ end
+ return title, report
+end
+
+local function do_carryover_gold()
+
+ local endlevel_data = wesnoth.scenario.end_level_data
+ local has_next_scenario = wesnoth.scenario.next ~= "" and wesnoth.scenario.next ~= "null" and endlevel_data.proceed_to_next_level
+ local is_victory = endlevel_data.is_victory
+ local is_observer = get_is_observer()
+ local is_replay = wesnoth.current.iser_is_replaying
+ local show_report = endlevel_data.carryover_report and (not is_observer) and (not is_replay)
+
+ local num_villages = get_num_villages()
+ local turns_left = math.max(0, wesnoth.scenario.turns - wesnoth.current.turn)
+ local num_persistent_teams = get_num_persistent_teams()
+
+ local title, report = get_popup_text_basic()
+
+ if has_next_scenario then
+ for __, side in ipairs(wesnoth.sides) do
+ if (not side.persistent) or side.lost then
+ goto continue
+ end
+ local finishing_bonus_per_turn = num_villages * side.village_gold + side.base_income
+ local finishing_bonus = side.carryover_bonus * finishing_bonus_per_turn * turns_left
+
+ side.carryover_gold = math.ceil((side.gold + finishing_bonus) * side.carryover_percentage / 100)
+
+ local is_human = side.controller == "human"
+ if (not side.is_local) or (not is_human) then
+ goto continue
+ end
+
+ if num_persistent_teams > 1 then
+ report = report .. "\n\n" .. side.side_name .. ""
+ end
+
+ report = report .. "\n" .. _("Remaining gold: ") .. half_signed_value(side.gold) .. ""
+
+ if side.carryover_bonus ~= 0 then
+ if turns_left > -1 then
+ report = report .. "\n\n" ..
+ _("Turns finished early: ") .. turns_left .. "\n" .. "" ..
+ _("Early finish bonus: ") .. finishing_bonus_per_turn .. _(" per turn") .. "\n" .. "" ..
+ _("Total bonus: ") .. finishing_bonus .. "\n"
+ end
+
+ report = report .. "" .. _("Total gold: ") .. half_signed_value(side.gold + finishing_bonus) .. ""
+ end
+
+ if side.gold > 0 then
+ report = report .. "\n" .. _("Carryover percentage: ") .. side.carryover_percentage .. ""
+ end
+
+ if side.carryover_add then
+ report = report .. "\n\n" .. _("Bonus gold: ") .. half_signed_value(side.carryover_gold) .. ""
+ else
+ report = report .. "\n\n" .. _("Retained gold: ") .. half_signed_value(side.carryover_gold) .. ""
+ end
+
+ local goldmsg = ""
+ -- Note that both strings are the same in English, but some languages will
+ -- want to translate them differently.
+ if side.carryover_add then
+ if side.carryover_gold > 0 then
+ goldmsg = _("You will start the next scenario with $gold on top of the defined minimum starting gold.",
+ "You will start the next scenario with $gold on top of the defined minimum starting gold.", side.carryover_gold)
+
+ else
+ goldmsg = _("You will start the next scenario with the defined minimum starting gold.",
+ "You will start the next scenario with the defined minimum starting gold.", side.carryover_gold)
+ end
+ else
+ goldmsg = _(
+ "You will start the next scenario with $gold or its defined minimum starting gold, whichever is higher.",
+ "You will start the next scenario with $gold or its defined minimum starting gold, whichever is higher.",
+ side.carryover_gold)
+ end
+
+ -- xgettext:no-c-format
+ report = report .. "\n" .. goldmsg:vformat{ gold = tostring(side.carryover_gold) }
+
+ ::continue::
+ end
+ end
+
+ if show_report then
+ gui.show_popup(title, report)
+ end
+end
+
+
+wesnoth.game_events.add {
+ name = "scenario_end",
+ id = "carryover_gold",
+ first_time_only = false,
+ --priority = -1000,
+ action = function()
+ do_carryover_gold()
+ end
+}
diff --git a/projectfiles/CodeBlocks/tests.cbp b/projectfiles/CodeBlocks/tests.cbp
index 7f8688bd8c4..c13f3e63a48 100644
--- a/projectfiles/CodeBlocks/tests.cbp
+++ b/projectfiles/CodeBlocks/tests.cbp
@@ -233,8 +233,6 @@
-
-
diff --git a/projectfiles/CodeBlocks/wesnoth.cbp b/projectfiles/CodeBlocks/wesnoth.cbp
index 1646e265477..87963d90c77 100644
--- a/projectfiles/CodeBlocks/wesnoth.cbp
+++ b/projectfiles/CodeBlocks/wesnoth.cbp
@@ -231,8 +231,6 @@
-
-
diff --git a/projectfiles/Xcode/The Battle for Wesnoth.xcodeproj/project.pbxproj b/projectfiles/Xcode/The Battle for Wesnoth.xcodeproj/project.pbxproj
index 87f5ca46721..2e419b2f269 100644
--- a/projectfiles/Xcode/The Battle for Wesnoth.xcodeproj/project.pbxproj
+++ b/projectfiles/Xcode/The Battle for Wesnoth.xcodeproj/project.pbxproj
@@ -661,7 +661,6 @@
7FDF4E8D9C94E7DA8F41F7BB /* tod_new_schedule.hpp in Headers */ = {isa = PBXBuildFile; fileRef = 5D46466DBCD81B13621C7342 /* tod_new_schedule.hpp */; };
805143B8BABF92CA79BEC8F5 /* gui_test_dialog.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 7FBD4033B4B52E9424819B5F /* gui_test_dialog.cpp */; };
80724CBB88A3B6C36D1E3199 /* spritesheet_generator.hpp in Headers */ = {isa = PBXBuildFile; fileRef = 3D284B9A81882806D8B25006 /* spritesheet_generator.hpp */; };
- 867141839BDB89BFE876E310 /* carryover_show_gold.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 09A440B1A671C45BE2924FB4 /* carryover_show_gold.cpp */; };
87744447951D17AA38BE5F48 /* mp_report.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 58C649488B3014E6F7254B62 /* mp_report.cpp */; };
8C704B6F99C824A4073EEBEE /* prompt.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 67044415B63F5888193BD7A6 /* prompt.cpp */; };
8D11072F0486CEB800E47090 /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1058C7A1FEA54F0111CA2CBB /* Cocoa.framework */; };
@@ -1128,7 +1127,6 @@
9577DD332C1E1C150031135F /* team_shared_vision.hpp in Headers */ = {isa = PBXBuildFile; fileRef = 9577DD322C1E1C150031135F /* team_shared_vision.hpp */; };
9577DD352C1E1E1D0031135F /* wesnoth_epoch.hpp in Headers */ = {isa = PBXBuildFile; fileRef = 9577DD342C1E1E1C0031135F /* wesnoth_epoch.hpp */; };
9577DD3E2C1E2EC60031135F /* preferences_list.hpp in Headers */ = {isa = PBXBuildFile; fileRef = 9577DD3D2C1E2EC60031135F /* preferences_list.hpp */; };
- 9577DD402C1E36170031135F /* carryover_show_gold.hpp in Headers */ = {isa = PBXBuildFile; fileRef = 9577DD3F2C1E36170031135F /* carryover_show_gold.hpp */; };
9577DD422C1E368B0031135F /* statistics_record.hpp in Headers */ = {isa = PBXBuildFile; fileRef = 9577DD412C1E368B0031135F /* statistics_record.hpp */; };
9577DD442C1E36D40031135F /* from_chars.hpp in Headers */ = {isa = PBXBuildFile; fileRef = 9577DD432C1E36D40031135F /* from_chars.hpp */; };
9577DD462C1E36E20031135F /* any.hpp in Headers */ = {isa = PBXBuildFile; fileRef = 9577DD452C1E36E20031135F /* any.hpp */; };
@@ -1143,7 +1141,6 @@
95EB8A55287A02EC00B09F95 /* top_level_drawable.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 95EB8A54287A02EC00B09F95 /* top_level_drawable.cpp */; };
95EB8A58287B138700B09F95 /* draw_manager.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 95EB8A50287A02B800B09F95 /* draw_manager.cpp */; };
95EB8A59287B139800B09F95 /* top_level_drawable.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 95EB8A54287A02EC00B09F95 /* top_level_drawable.cpp */; };
- 97714C7A9FF444E29DCEF0BA /* carryover_show_gold.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 09A440B1A671C45BE2924FB4 /* carryover_show_gold.cpp */; };
99494BD0ABBAE79FB3814E00 /* charconv.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0CDC443798CB3254283483D0 /* charconv.cpp */; };
9B4B41D29C90B05F03DE21B0 /* edit_pbl_translation.hpp in Headers */ = {isa = PBXBuildFile; fileRef = C679447D91FD3623CC852FF8 /* edit_pbl_translation.hpp */; };
9C2743DE8100448B66F7E0AF /* combobox.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 875E45698F8A8D5B750E7317 /* combobox.cpp */; };
@@ -1600,7 +1597,6 @@
000000000000000000000010 /* network_download_file.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = network_download_file.hpp; sourceTree = ""; };
00574699A982AA23F12B39E0 /* edit_pbl_translation.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = edit_pbl_translation.cpp; sourceTree = ""; };
0110429EAA81AED07D53B749 /* gui_test_dialog.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = gui_test_dialog.hpp; sourceTree = ""; };
- 09A440B1A671C45BE2924FB4 /* carryover_show_gold.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = carryover_show_gold.cpp; sourceTree = ""; };
0B0F48CE9CF65D9813BE6CDC /* multiline_text.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = multiline_text.cpp; sourceTree = ""; };
0CDC443798CB3254283483D0 /* charconv.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = charconv.cpp; path = charconv.cpp; sourceTree = ""; };
1058C7A1FEA54F0111CA2CBB /* Cocoa.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Cocoa.framework; path = System/Library/Frameworks/Cocoa.framework; sourceTree = SDKROOT; };
@@ -2435,7 +2431,6 @@
9577DD322C1E1C150031135F /* team_shared_vision.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = team_shared_vision.hpp; sourceTree = ""; };
9577DD342C1E1E1C0031135F /* wesnoth_epoch.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = wesnoth_epoch.hpp; sourceTree = ""; };
9577DD3D2C1E2EC60031135F /* preferences_list.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; name = preferences_list.hpp; path = preferences/preferences_list.hpp; sourceTree = ""; };
- 9577DD3F2C1E36170031135F /* carryover_show_gold.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = carryover_show_gold.hpp; sourceTree = ""; };
9577DD412C1E368B0031135F /* statistics_record.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = statistics_record.hpp; sourceTree = ""; };
9577DD432C1E36D40031135F /* from_chars.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = from_chars.hpp; sourceTree = ""; };
9577DD452C1E36E20031135F /* any.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = any.hpp; sourceTree = ""; };
@@ -3269,8 +3264,6 @@
91B621A11B76A3CC00B00E0F /* build_info.cpp */,
91B621A31B76A5FA00B00E0F /* build_info.hpp */,
9577DD1A2C1E0AF40031135F /* campaign_type.hpp */,
- 09A440B1A671C45BE2924FB4 /* carryover_show_gold.cpp */,
- 9577DD3F2C1E36170031135F /* carryover_show_gold.hpp */,
ECFB9FA7193BFAD900146ED0 /* carryover.cpp */,
91B621811B766F1900B00E0F /* carryover.hpp */,
918C8A161D05F9AA009744A0 /* chat_command_handler.cpp */,
@@ -5233,7 +5226,6 @@
3DED4C43AC1B737C15549CEC /* rich_label.hpp in Headers */,
9577DD292C1E0E530031135F /* sort_order.hpp in Headers */,
9C6342BC8A95B6D23D384486 /* gui_test_dialog.hpp in Headers */,
- 9577DD402C1E36170031135F /* carryover_show_gold.hpp in Headers */,
80724CBB88A3B6C36D1E3199 /* spritesheet_generator.hpp in Headers */,
0DA840E1AD033775DD626F42 /* markup.hpp in Headers */,
F7524948ADF9BC097E6D8DBC /* charconv.hpp in Headers */,
@@ -5979,7 +5971,6 @@
46F92E212174F6A400602C1C /* mp_change_control.cpp in Sources */,
36B146FAA79A55E9F43723B1 /* general.cpp in Sources */,
3C254DF5B7DF196F2041955F /* mp_report.cpp in Sources */,
- 97714C7A9FF444E29DCEF0BA /* carryover_show_gold.cpp in Sources */,
6D574EACA3483ABEE72819F0 /* statistics_record.cpp in Sources */,
4E19429E82899A42A73BBE91 /* choose_addon.cpp in Sources */,
36D74F7F8D7655ACCABE562D /* edit_pbl.cpp in Sources */,
@@ -6654,7 +6645,6 @@
915C68EC1DF1DCB000594B07 /* color.cpp in Sources */,
4291489DA38012477DA3BA7C /* general.cpp in Sources */,
87744447951D17AA38BE5F48 /* mp_report.cpp in Sources */,
- 867141839BDB89BFE876E310 /* carryover_show_gold.cpp in Sources */,
3E9A4297B4A2828C569C8927 /* statistics_record.cpp in Sources */,
E79249078ACE777D1E219DED /* choose_addon.cpp in Sources */,
04C748F7835C62498D27442D /* edit_pbl.cpp in Sources */,
diff --git a/source_lists/wesnoth b/source_lists/wesnoth
index d51381d492c..ceefc09a774 100644
--- a/source_lists/wesnoth
+++ b/source_lists/wesnoth
@@ -61,7 +61,6 @@ animated.cpp
attack_prediction.cpp
build_info.cpp
carryover.cpp
-carryover_show_gold.cpp
chat_command_handler.cpp
chat_events.cpp
chat_log.cpp
diff --git a/src/carryover_show_gold.cpp b/src/carryover_show_gold.cpp
deleted file mode 100644
index 28343a5f724..00000000000
--- a/src/carryover_show_gold.cpp
+++ /dev/null
@@ -1,158 +0,0 @@
-/*
- Copyright (C) 2003 - 2024
- by David White
- Part of the Battle for Wesnoth Project https://www.wesnoth.org/
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY.
-
- See the COPYING file for more details.
-*/
-
-#include "carryover_show_gold.hpp"
-
-#include "log.hpp"
-#include "team.hpp"
-#include "game_state.hpp"
-#include "gettext.hpp"
-#include "gui/dialogs/transient_message.hpp"
-#include "formula/string_utils.hpp"
-#include "map/map.hpp"
-#include "serialization/markup.hpp"
-#include
-
-static lg::log_domain log_engine("engine");
-#define LOG_NG LOG_STREAM(info, log_engine)
-#define ERR_NG LOG_STREAM(err, log_engine)
-
-
-void carryover_show_gold(game_state& state, bool hidden, bool is_observer, bool is_test)
-{
- assert(state.end_level_data_);
- game_board& board = state.board_;
- const end_level_data& end_level = *state.end_level_data_;
- const bool is_victory = end_level.is_victory;
- // We need to write the carryover amount to the team that's why we need non const
- std::vector& teams = board.teams();
-
- // maybe this can be the case for scenario that only contain a story and end during the prestart event ?
- if(teams.size() < 1) {
- return;
- }
-
- std::ostringstream report;
- std::string title;
-
-
- if(is_observer) {
- title = _("Scenario Report");
- } else if(is_victory) {
- title = _("Victory");
- report << markup::bold(_("You have emerged victorious!"));
- } else {
- title = _("Defeat");
- report << _("You have been defeated!");
- }
-
- const std::string& next_scenario = state.get_game_data()->next_scenario();
- const bool has_next_scenario = !next_scenario.empty() && next_scenario != "null";
-
- int persistent_teams = 0;
- for(const team& t : teams) {
- if(t.persistent()) {
- ++persistent_teams;
- }
- }
-
- if(persistent_teams > 0 && ((has_next_scenario && end_level.proceed_to_next_level) || is_test)) {
- const gamemap& map = board.map();
- const tod_manager& tod = state.get_tod_man();
-
- const int turns_left = std::max(0, tod.number_of_turns() - tod.turn());
- for(team& t : teams) {
- if(!t.persistent() || t.lost()) {
- continue;
- }
-
- const int finishing_bonus_per_turn = map.villages().size() * t.village_gold() + t.base_income();
- const int finishing_bonus = t.carryover_bonus() * finishing_bonus_per_turn * turns_left;
-
- t.set_carryover_gold(div100rounded((t.gold() + finishing_bonus) * t.carryover_percentage()));
-
- if(!t.is_local_human()) {
- continue;
- }
-
- if(persistent_teams > 1) {
- report << "\n\n" << markup::bold(t.side_name());
- }
-
- report << "\n" << markup::tag("small", _("Remaining gold: "), utils::half_signed_value(t.gold()));
-
- if(t.carryover_bonus() != 0) {
- if(turns_left > -1) {
- report << "\n\n"
- << markup::bold(_("Turns finished early: "), turns_left) << "\n"
- << markup::tag("small",
- _("Early finish bonus: "), finishing_bonus_per_turn, _(" per turn"), "\n",
- _("Total bonus: "), finishing_bonus, "\n");
- }
-
- report << markup::tag("small", _("Total gold: "), utils::half_signed_value(t.gold() + finishing_bonus));
- }
-
- if(t.gold() > 0) {
- report << "\n" << markup::tag("small", _("Carryover percentage: "), t.carryover_percentage());
- }
-
- if(t.carryover_add()) {
- report << "\n\n" << markup::tag("big", markup::bold(_("Bonus gold: "), utils::half_signed_value(t.carryover_gold())));
- } else {
- report << "\n\n" << markup::tag("big", markup::bold(_("Retained gold: "), utils::half_signed_value(t.carryover_gold())));
- }
-
- std::string goldmsg;
- utils::string_map symbols;
-
- symbols["gold"] = lexical_cast_default(t.carryover_gold());
-
- // Note that both strings are the same in English, but some languages will
- // want to translate them differently.
- if(t.carryover_add()) {
- if(t.carryover_gold() > 0) {
- goldmsg = VNGETTEXT(
- "You will start the next scenario with $gold on top of the defined minimum starting gold.",
- "You will start the next scenario with $gold on top of the defined minimum starting gold.",
- t.carryover_gold(), symbols
- );
-
- } else {
- goldmsg = VNGETTEXT(
- "You will start the next scenario with the defined minimum starting gold.",
- "You will start the next scenario with the defined minimum starting gold.",
- t.carryover_gold(), symbols
- );
- }
- } else {
- goldmsg = VNGETTEXT(
- "You will start the next scenario with $gold or its defined minimum starting gold, "
- "whichever is higher.",
- "You will start the next scenario with $gold or its defined minimum starting gold, "
- "whichever is higher.",
- t.carryover_gold(), symbols
- );
- }
-
- // xgettext:no-c-format
- report << "\n" << goldmsg;
- }
- }
-
- if(end_level.transient.carryover_report && !hidden) {
- gui2::show_transient_message(title, report.str(), "", true);
- }
-}
diff --git a/src/carryover_show_gold.hpp b/src/carryover_show_gold.hpp
deleted file mode 100644
index 390ca3a7d1a..00000000000
--- a/src/carryover_show_gold.hpp
+++ /dev/null
@@ -1,19 +0,0 @@
-/*
- Copyright (C) 2022 - 2024
- Part of the Battle for Wesnoth Project https://www.wesnoth.org/
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY.
-
- See the COPYING file for more details.
-*/
-
-#pragma once
-class game_state;
-/// calculates the amount of gold carried over for each team,
-/// stores the data in the team object and shows the carryover message
-void carryover_show_gold(game_state& state, bool hidden, bool is_observer, bool is_test);
diff --git a/src/playsingle_controller.cpp b/src/playsingle_controller.cpp
index 4cc74bfa86b..922fa6aa35a 100644
--- a/src/playsingle_controller.cpp
+++ b/src/playsingle_controller.cpp
@@ -25,7 +25,6 @@
#include "ai/manager.hpp"
#include "ai/testing.hpp"
#include "display_chat_manager.hpp"
-#include "carryover_show_gold.hpp"
#include "formula/string_utils.hpp"
#include "game_end_exceptions.hpp"
#include "game_events/pump.hpp"
@@ -410,8 +409,6 @@ void playsingle_controller::do_end_level()
}
persist_.end_transaction();
- carryover_show_gold(gamestate(), is_observer() || is_replay(), is_observer(), saved_game_.classification().is_test());
-
}
level_result::type playsingle_controller::play_scenario(const config& level)