From 1a6f005a3629f4b1714a7750e8535aff9642ebb8 Mon Sep 17 00:00:00 2001 From: Nat Quayle Nelson Date: Wed, 25 Sep 2024 10:46:36 -0500 Subject: [PATCH] change --advance-time to --verbose, w/ better replay behavior --- src/game/boe.actions.cpp | 7 ++++--- src/game/boe.main.cpp | 11 ++++------- src/tools/replay.cpp | 38 ++++++++++++++++++++++++++++++++++++-- 3 files changed, 44 insertions(+), 12 deletions(-) diff --git a/src/game/boe.actions.cpp b/src/game/boe.actions.cpp index b759af8b..1e42cfda 100644 --- a/src/game/boe.actions.cpp +++ b/src/game/boe.actions.cpp @@ -109,7 +109,8 @@ extern sf::RenderWindow mini_map; extern std::shared_ptr text_sbar,item_sbar,shop_sbar; extern short shop_identify_cost, shop_recharge_amount; -extern bool record_advance_time; +extern bool record_verbose; +extern bool replay_verbose; const char *dir_string[] = {"North", "NorthEast", "East", "SouthEast", "South", "SouthWest", "West", "NorthWest"}; char get_new_terrain(); @@ -1628,14 +1629,14 @@ bool handle_action(const sf::Event& event, cFramerateLimiter& fps_limiter) { } void advance_time(bool did_something, bool need_redraw, bool need_reprint) { - if(recording && record_advance_time){ + if(recording && record_verbose){ std::map info; info["did_something"] = bool_to_str(did_something); info["need_redraw"] = bool_to_str(need_redraw); info["need_reprint"] = bool_to_str(need_reprint); record_action("advance_time", info); } - if(replaying && record_advance_time){ + if(replaying && replay_verbose){ if(next_action_type() == "advance_time"){ std::string _last_action_type = last_action_type; Element& element = pop_next_action(); diff --git a/src/game/boe.main.cpp b/src/game/boe.main.cpp index 3795d458..869cee79 100644 --- a/src/game/boe.main.cpp +++ b/src/game/boe.main.cpp @@ -234,7 +234,8 @@ static void init_ui() { init_buttons(); } -bool record_advance_time = false; +extern bool record_verbose; +extern bool replay_verbose; static void process_args(int argc, char* argv[]) { preprocess_args(argc, argv); @@ -245,7 +246,7 @@ static void process_args(int argc, char* argv[]) { boost::optional replay_speed; cli |= clara::Opt(record_to, "record")["--record"]("Records a replay of your session to the specified XML file."); cli |= clara::Opt(record_unique)["--unique"]("When recording, automatically insert a timestamp into the filename to guarantee uniqueness."); - cli |= clara::Opt(record_advance_time)["--advance-time"]("Record and validate advance_time() calls for internal testing of the replay system."); + cli |= clara::Opt(record_verbose)["--verbose"]("Record extra information for internal testing of the replay system."); cli |= clara::Opt(replay, "replay-file")["--replay"]("Replays a previously-recorded session from the specified XML file."); cli |= clara::Opt(replay_speed, "fps")["--replay-speed"]("Specifies how quickly actions are processed while replaying"); cli |= clara::Arg(saved_game, "save-file")("Launch and load a saved game file."); @@ -584,11 +585,7 @@ static void replay_next_action() { }else if(t == "cancel_item_target"){ cancel_item_target(); }else if(t == "advance_time"){ - if(record_advance_time){ - throw std::string { "Replay system internal error! advance_time() was supposed to be called by the last action, but wasn't: " } + _last_action_type; - }else{ - throw std::string { "The action log you're replaying contains advance_time() recordings. The additional --advance-time flag is required to process it." }; - } + throw std::string { "Replay system internal error! advance_time() was supposed to be called by the last action, but wasn't: " } + _last_action_type; }else{ std::ostringstream sstr; sstr << "Couldn't replay action: " << next_action; diff --git a/src/tools/replay.cpp b/src/tools/replay.cpp index ced70963..eedefc60 100644 --- a/src/tools/replay.cpp +++ b/src/tools/replay.cpp @@ -2,7 +2,6 @@ // Input recording system -#include "ticpp.h" #include #include #include @@ -10,12 +9,15 @@ #include #include #include -#include "tools/framerate_limiter.hpp" #include #include #include +#include #include + +#include "ticpp.h" #include "gfx/render_shapes.hpp" +#include "tools/framerate_limiter.hpp" #ifndef MSBUILD_GITREV #include "tools/gitrev.hpp" #endif @@ -25,6 +27,9 @@ using base64 = cppcodec::base64_rfc4648; bool recording = false; bool replaying = false; +bool record_verbose = false; +bool replay_verbose = false; + std::string last_action_type; using namespace ticpp; @@ -72,8 +77,31 @@ bool init_action_log(std::string command, std::string file) { else if (command == "replay") { try { log_document.LoadFile(file); + Element* root = log_document.FirstChildElement(); next_action = root->FirstChildElement(); + + // Set replay_verbose automatically if the log has verbose elements. + // This must be done before starting the replay, not when the first + // verbose element appears, because the *absence* of a verbose elements + // is meaningful in a verbose replay. + + // This is an O(N) traversal, but it won't matter, because advance_time + // elements are the most common elements in verbose logs. + + // Specifying replay_verbose manually and incorrectly would cause confusing + // errors. + std::vector verbose_actions = { "advance_time" }; + + Element* checking_action = next_action; + do{ + if(std::find(verbose_actions.begin(), verbose_actions.end(), checking_action->Value()) != verbose_actions.end()){ + replay_verbose = true; + break; + } + checking_action = checking_action->NextSiblingElement(false); + }while(checking_action != nullptr); + replaying = true; } catch(...) { std::cout << "Failed to load file " << file << std::endl; @@ -159,6 +187,12 @@ Element& pop_next_action(std::string expected_action_type) { // control_click actions are not meaningful for debugging if (to_return->Value() != "control_click"){ last_action_type = to_return->Value(); + + if(replay_verbose){ + // Verbose replays are for internal testing, so this console output won't bother + // anyone and is very helpful: + std::cout << last_action_type << std::endl; + } } return *to_return;