JaffarPlus
High-performance best-first search optimizer for tool-assisted speedruns
Loading...
Searching...
No Matches
runner.hpp
Go to the documentation of this file.
1#pragma once
2
9#include "game.hpp"
11#include "inputSet.hpp"
12#include <atomic>
13#include <cstdint>
14#include <gameList.hpp>
15#include <jaffarCommon/bitwise.hpp>
16#include <jaffarCommon/deserializers/contiguous.hpp>
17#include <jaffarCommon/hash.hpp>
18#include <jaffarCommon/json.hpp>
19#include <jaffarCommon/logger.hpp>
20#include <jaffarCommon/serializers/contiguous.hpp>
21#include <memory>
22#include <unordered_set>
23#include <vector>
24
25namespace jaffarPlus
26{
27
37class Runner final
38{
39public:
49 Runner(std::unique_ptr<Game>& game, const nlohmann::json& config) : _game(std::move(game))
50 {
51 // Mutable copy so unrecognized Runner keys can be flagged after the known ones are consumed
52 auto configRemaining = config;
53
54 _hashStepTolerance = jaffarCommon::json::popNumber<uint32_t>(configRemaining, "Hash Step Tolerance");
55
56 // The input-history strategy (None / Raw / Trie) is selected and validated by the InputHistory
57 // factory from this object; stored here and built in initialize() once the input set is known.
58 _inputHistoryConfig = jaffarCommon::json::popObject(configRemaining, "Store Input History");
59
60 // Storing game inputs for delayed parsing
61 _allowedInputSetsJs = jaffarCommon::json::popArray<nlohmann::json>(configRemaining, "Allowed Input Sets");
62
63 // Print option: do not print allowed inputs
64 _showAllowedInputs = jaffarCommon::json::popBoolean(configRemaining, "Show Allowed Inputs");
65
66 // Print option: do not print placeholders for inputs not supported in this frame
67 _showEmptyInputSlots = jaffarCommon::json::popBoolean(configRemaining, "Show Empty Input Slots");
68
69 // Stores candidate inputs
70 _testCandidateInputs = jaffarCommon::json::popBoolean(configRemaining, "Test Candidate Inputs");
71
72 // Getting candidate input sets
73 _candidateInputSetsJs = jaffarCommon::json::popArray<nlohmann::json>(configRemaining, "Candidate Input Sets");
74
75 // Getting frame skip configuration
76 auto frameskipJs = jaffarCommon::json::popObject(configRemaining, "Frameskip");
77 _frameskipRate = jaffarCommon::json::popNumber<size_t>(frameskipJs, "Rate");
78 _frameskipUseCustomInput = jaffarCommon::json::popBoolean(frameskipJs, "Use Custom Input");
79 _frameskipCustomInput = jaffarCommon::json::popString(frameskipJs, "Custom Input");
80 jaffarCommon::json::checkEmpty(frameskipJs, "Runner Configuration > Frameskip");
81
82 // Option to bypass hash calculation via MetroHash and get it straight from the game
83 _bypassHashCalculation = jaffarCommon::json::popBoolean(configRemaining, "Bypass Hash Calculation");
84
85 // Any remaining Runner key is unrecognized
86 jaffarCommon::json::checkEmpty(configRemaining, "Runner Configuration");
87 }
88
99 {
100 if (_isInitialized == true) JAFFAR_THROW_LOGIC("This runner instance was already initialized");
101
102 // Initializing game, if not already initialized
103 if (_game->isInitialized() == false) _game->initialize();
104
105 // Parsing possible game inputs
106 for (const auto& inputSetJs : _allowedInputSetsJs) _allowedInputSets.push_back(parseInputSet(inputSetJs));
107
108 // If testing candidate inputs, parse them now
109 if (_testCandidateInputs == true)
110 for (const auto& inputSetJs : _candidateInputSetsJs) _candidateInputSets.push_back(parseInputSet(inputSetJs));
111
112 // Parsing inputs declared directly by the game's code
113 for (const auto& input : _game->getAllPossibleInputs()) registerInput(input);
114
115 // Resolve the custom frameskip input index once (it is constant), so advanceState() can reuse it
116 // instead of re-hashing + re-looking-it-up every skipped frame. Also validates it early -- a bad
117 // "Custom Input" now fails here at init rather than crashing deep in the simulation loop.
119
120 // Build the configured input-history strategy now that the input set (hence _maxInputIndex) is known.
121 // Worker runners share a backing injected by the engine (setInputHistoryBacking); a standalone runner
122 // (player / driver) makes its own private backing here.
123 if (_historyBacking == nullptr)
124 {
125 _historyBacking = inputHistory::createSharedBacking(_inputHistoryConfig, _historyNumShards);
126 _historyShardId = 0;
127 }
129 }
130
134 __INLINE__ void setInputHistoryBacking(const std::shared_ptr<void>& backing, const uint32_t shardId, const uint32_t numShards)
135 {
136 _historyBacking = backing;
137 _historyShardId = shardId;
138 _historyNumShards = numShards;
139 }
140
142 __INLINE__ const nlohmann::json& getInputHistoryConfig() const { return _inputHistoryConfig; }
143
145 __INLINE__ InputHistory* getInputHistory() const { return _inputHistory.get(); }
146
157 std::unique_ptr<InputSet> parseInputSet(const nlohmann::json& inputSetJs)
158 {
159 // Creating new input set to add
160 auto inputSet = std::make_unique<InputSet>();
161
162 // Getting input set condition array
163 const auto& conditions = jaffarCommon::json::getArray<nlohmann::json>(inputSetJs, "Conditions");
164
165 // Getting input string array
166 const auto& inputsJs = jaffarCommon::json::getArray<std::string>(inputSetJs, "Inputs");
167
168 // Parsing input set conditions
169 for (const auto& condition : conditions) inputSet->addCondition(_game->parseCondition(condition));
170
171 // Parsing input set inputs
172 for (const auto& input : inputsJs) inputSet->addInput(registerInput(input));
173
174 // Keep track of maximum size (for better output)
175 _largestInputSetSize = std::max(_largestInputSetSize, inputSet->getInputIndexes().size());
176
177 // Getting stop evaluating flag
178 inputSet->setStopInputEvaluationFlag(jaffarCommon::json::getBoolean(inputSetJs, "Stop Input Evaluation"));
179
180 // Returning new input set
181 return inputSet;
182 }
183
192 InputSet::inputIndex_t registerInput(const std::string& input)
193 {
194 // Getting input hash
195 const auto inputHash = jaffarCommon::hash::hashString(input);
196
197 // Getting index for the new input
198 InputSet::inputIndex_t inputIdx = _game->getEmulator()->registerInput(input);
199
200 // Adding new input hash->index to the map
201 _inputHashMap[inputHash] = inputIdx;
202
203 // Adding new input index->string to the map
204 _inputStringMap[inputIdx] = input;
205
206 // Register maximum input index to determine how many bytes to use for input history storage
207 _maxInputIndex = std::max(_maxInputIndex, inputIdx + 1);
208
209 // Returning this input's index (either new or the one registered before)
210 return inputIdx;
211 }
212
222 std::vector<InputSet::inputIndex_t> getInputsFromInputSets(const std::vector<std::unique_ptr<InputSet>>& inputSets) const
223 {
224 // Storage for the possible input set
225 std::vector<InputSet::inputIndex_t> possibleInputs;
226
227 // For all registered input sets, see which ones satisfy their conditions and add them
228 for (const auto& inputSet : inputSets)
229 if (inputSet->evaluate() == true)
230 {
231 possibleInputs.insert(possibleInputs.end(), inputSet->getInputIndexes().begin(), inputSet->getInputIndexes().end());
232
233 // Getting stop evaluating flag
234 bool stopEvaluating = inputSet->getStopInputEvaluationFlag();
235
236 // If stop evaluation is set, then return now
237 if (stopEvaluating) break;
238 }
239
240 // Return possible inputs
241 return possibleInputs;
242 }
243
251 __INLINE__ const auto getAllowedInputs() const
252 {
253 // Getting possible inputs based on the configuration file
254 auto allowedInputs = getInputsFromInputSets(_allowedInputSets);
255
256 // Getting additional inputs based on the custom game function
257 _game->getAdditionalAllowedInputs(allowedInputs);
258
259 return allowedInputs;
260 }
261
266 __INLINE__ const auto getCandidateInputs() const { return getInputsFromInputSets(_candidateInputSets); }
267
274 __INLINE__ jaffarPlus::InputSet::inputIndex_t getInputIndex(const std::string& input) const
275 {
276 // Getting input hash
277 const auto inputHash = jaffarCommon::hash::hashString(input);
278
279 // Getting input index from the hash map
280 auto it = _inputHashMap.find(inputHash);
281 if (it == _inputHashMap.end()) JAFFAR_THROW_LOGIC("[ERROR] Input '%s' provided but has not been registered as allowed input first.\n", input.c_str());
282 const auto inputIndex = it->second;
283
284 return inputIndex;
285 }
286
292 bool isInputRegistered(const std::string& inputString)
293 {
294 // Getting input hash
295 const auto inputHash = jaffarCommon::hash::hashString(inputString);
296
297 // Returning true if found; false, otherwise
298 return _inputHashMap.contains(inputHash);
299 }
300
309 __INLINE__ void advanceState(const InputSet::inputIndex_t inputIdx)
310 {
311 // Safety check -- Disabled, for performance
312 // if (_inputStringMap.contains(inputIdx) == false) JAFFAR_THROW_RUNTIME("Move Index %u not found in runner\n", inputIdx);
313
314 // Performing the requested input
315 _game->advanceState(inputIdx);
316
317 // Pushing normal input into the history
318 pushInput(inputIdx);
319
320 // If frameskip was set, execute it now
321 for (size_t i = 0; i < _frameskipRate; i++)
322 {
323 InputSet::inputIndex_t frameskipInputIdx = inputIdx;
324 if (_frameskipUseCustomInput) frameskipInputIdx = _frameskipCustomInputIdx;
325 _game->advanceState(frameskipInputIdx);
326 pushInput(frameskipInputIdx);
327 }
328 }
329
338 __INLINE__ void pushInput(const InputSet::inputIndex_t inputIdx)
339 {
340 _inputHistory->pushInput(_stepCount, inputIdx);
341 _stepCount++;
342 }
343
346 __INLINE__ void setStepCount(const size_t stepCount) { _stepCount = stepCount; }
347
351 __INLINE__ void setSearchStep(const size_t searchStep) { _stepCount = searchStep * (_frameskipRate + 1); }
352
354 __INLINE__ size_t getStepCount() const { return _stepCount; }
355
360 __INLINE__ void serializeState(jaffarCommon::serializer::Base& serializer) const
361 {
362 // Game state, then the self-contained ("full") input-history form (used by in-memory, run-scoped
363 // snapshots: the player's initial state and the best/worst/win buffers).
364 _game->serializeState(serializer);
365 _inputHistory->serializeFull(serializer);
366 }
367
372 __INLINE__ void deserializeState(jaffarCommon::deserializer::Base& deserializer)
373 {
374 _game->deserializeState(deserializer);
375 // The step counter is not part of the stream; the caller sets it (via setStepCount/setSearchStep) before
376 // deserializing so strategies that rebuild from the path length (the trie) have it available.
377 _inputHistory->deserializeFull(deserializer, _stepCount);
378 }
379
384 __INLINE__ size_t getStateSize() const
385 {
386 jaffarCommon::serializer::Contiguous s;
387 this->serializeState(s);
388 return s.getOutputSize();
389 }
390
391 // ---- Hot/cold split ------------------------------------------------------------------------------
392 // The State DB stores the per-state "path" (the bit-packed input history + step counter) in a
393 // parallel "cold" slab instead of the hot state slot it hashes/advances every step. These helpers let
394 // it write/measure the two parts separately. serializeState()/getStateSize() above are unchanged and
395 // still produce the FULL state for every other caller (player, playback, on-disk checkpoints).
396
398 __INLINE__ void serializeHotState(jaffarCommon::serializer::Base& serializer) const { _game->serializeState(serializer); }
400 __INLINE__ void deserializeHotState(jaffarCommon::deserializer::Base& deserializer) { _game->deserializeState(deserializer); }
401
404 __INLINE__ void serializeHistory(jaffarCommon::serializer::Base& serializer) const { _inputHistory->serializeCold(serializer); }
406 __INLINE__ void deserializeHistory(jaffarCommon::deserializer::Base& deserializer) { _inputHistory->deserializeCold(deserializer); }
407
409 __INLINE__ size_t getHotStateSize() const
410 {
411 jaffarCommon::serializer::Contiguous s;
412 this->serializeHotState(s);
413 return s.getOutputSize();
414 }
416 __INLINE__ size_t getHistorySize() const { return _inputHistory->getColdSize(); }
417
426 __INLINE__ jaffarCommon::hash::hash_t computeHash() const
427 {
428 // If normal hash calculation is to be bypassed, get it straight from the game
429 if (_bypassHashCalculation == true) return _game->getDirectStateHash();
430
431 // Storage for hash calculation
432 MetroHash128 hashEngine;
433
434 // Calculating hash tolerance stage
435 auto hashStepToleranceStage = getHashStepToleranceStage();
436
437 // Hashing step tolerance stage
438 hashEngine.Update(hashStepToleranceStage);
439
440 // Processing hashing from the game proper
441 _game->computeHash(hashEngine);
442
443 jaffarCommon::hash::hash_t result;
444 hashEngine.Finalize(reinterpret_cast<uint8_t*>(&result));
445 return result;
446 }
447
456 std::string getInputHistoryString() const { return _inputHistory->toString(_inputStringMap, _stepCount); }
457
463 std::string getInputStringFromIndex(const InputSet::inputIndex_t input) { return _inputStringMap[input]; }
464
472 void printInfo() const
473 {
474 // Getting state hash
475 const auto hash = jaffarCommon::hash::hashToString(computeHash());
476
477 // Calculating hash tolerance stage
478 auto hashStepToleranceStage = getHashStepToleranceStage();
479
480 // Memory usage
481 jaffarCommon::logger::log("[J+] + Input History Type: %s (cold %lu B, full %lu B)\n", inputHistory::getType(_inputHistoryConfig).c_str(),
482 _inputHistory->getColdSize(), _inputHistory->getFullSize());
483
484 // Printing runner state
485 jaffarCommon::logger::log("[J+] + Current Input Count: %lu\n", _stepCount);
486 jaffarCommon::logger::log("[J+] + Hash: %s\n", hash.c_str());
487 jaffarCommon::logger::log("[J+] + Hash Step Tolerance Stage: %u / %u\n", hashStepToleranceStage, _hashStepTolerance);
488
489 // Printing frameskip information
490 if (_frameskipRate > 0) jaffarCommon::logger::log("[J+] + Frameskip Rate: %lu\n", _frameskipRate);
491
492 // Check whether we want to print inputs
493 if (_showAllowedInputs == true)
494 {
495 // Getting allowed inputs
496 const auto& possibleInputs = getAllowedInputs();
497
498 // Printing them
499 jaffarCommon::logger::log("[J+] + Allowed Inputs:\n");
500
501 size_t currentInputIdx = 0;
502 for (const auto inputIdx : possibleInputs)
503 {
504 jaffarCommon::logger::log("[J+] + '%s'\n", _inputStringMap.at(inputIdx).c_str());
505 currentInputIdx++;
506 }
507
509 for (; currentInputIdx < _largestInputSetSize; currentInputIdx++) jaffarCommon::logger::log("[J+] + ----- \n");
510 }
511 }
512
514 __INLINE__ uint32_t getHashStepToleranceStage() const { return (uint32_t)_stepCount % (_hashStepTolerance + 1); }
516 __INLINE__ Game* getGame() const { return _game.get(); }
517
527 static std::unique_ptr<Runner> getRunner(const nlohmann::json& emulatorConfig, const nlohmann::json& gameConfig, const nlohmann::json& runnerConfig)
528 {
529 // Getting Game
530 auto game = Game::getGame(emulatorConfig, gameConfig);
531
532 // Creating new runner
533 auto r = std::make_unique<Runner>(game, runnerConfig);
534
535 // Returning runner
536 return r;
537 }
538
540 __INLINE__ bool isInitialized() const { return _isInitialized; }
541
542private:
543 bool _isInitialized = false;
544
545 std::unique_ptr<Game> _game;
546
548
549 // --- Input history (strategy-agnostic) -----------------------------------------------------------
550 nlohmann::json _inputHistoryConfig;
551 std::unique_ptr<InputHistory> _inputHistory;
552 size_t _stepCount = 0;
554 std::shared_ptr<void> _historyBacking;
555 uint32_t _historyShardId = 0;
556 uint32_t _historyNumShards = 2;
557
559
561 // Input processing variables
563
565
566 std::map<jaffarCommon::hash::hash_t, InputSet::inputIndex_t> _inputHashMap;
567
568 std::map<InputSet::inputIndex_t, std::string> _inputStringMap;
569
571 // Frameskip. These are frames that are simply skipped over, but they inputs registered nevertheless
573
575
577
579
583
585 // Allowed and candidate input sets
587
588 std::vector<nlohmann::json> _allowedInputSetsJs;
589
590 std::vector<nlohmann::json> _candidateInputSetsJs;
591
592 std::vector<std::unique_ptr<InputSet>> _candidateInputSets;
593
594 std::vector<std::unique_ptr<InputSet>> _allowedInputSets;
595
597
599
601
603};
604
605} // namespace jaffarPlus
Abstract base class for a JaffarPlus game.
Definition game.hpp:39
static std::unique_ptr< Game > getGame(const nlohmann::json &emulatorConfig, const nlohmann::json &gameConfig)
Factory that constructs the concrete game matching the given configuration.
Abstract strategy for remembering the input path that produced each search state.
size_t inputIndex_t
Type used to index an input.
Definition inputSet.hpp:29
Owns a Game instance and advances it according to configured inputs.
Definition runner.hpp:38
std::unique_ptr< InputSet > parseInputSet(const nlohmann::json &inputSetJs)
Builds an InputSet from its JSON description.
Definition runner.hpp:157
std::unique_ptr< InputHistory > _inputHistory
The configured strategy instance (built in initialize()).
Definition runner.hpp:551
void setStepCount(const size_t stepCount)
Sets the step counter directly (its input-count value).
Definition runner.hpp:346
InputSet::inputIndex_t _frameskipCustomInputIdx
Resolved index of the custom frameskip input, computed once at initialize() so advanceState() does no...
Definition runner.hpp:582
bool _showAllowedInputs
Whether allowed inputs are printed in printInfo.
Definition runner.hpp:602
InputSet::inputIndex_t registerInput(const std::string &input)
Registers an input string and returns its numeric index.
Definition runner.hpp:192
bool _isInitialized
Whether the runner has been initialized.
Definition runner.hpp:543
uint32_t getHashStepToleranceStage() const
Returns the current hash-step-tolerance stage (current input count modulo tolerance + 1).
Definition runner.hpp:514
const auto getAllowedInputs() const
Returns the inputs currently allowed for the game's state.
Definition runner.hpp:251
bool _showEmptyInputSlots
Whether placeholders are printed for unused input slots.
Definition runner.hpp:600
std::shared_ptr< void > _historyBacking
Shared backing (e.g. the one trie), injected by the engine or owned privately.
Definition runner.hpp:554
size_t _frameskipRate
Number of frames to skip after each applied input.
Definition runner.hpp:574
std::string getInputStringFromIndex(const InputSet::inputIndex_t input)
Returns the input string registered for an input index.
Definition runner.hpp:463
size_t getStateSize() const
Computes the size in bytes of the serialized runner state.
Definition runner.hpp:384
void initialize()
Initializes the runner: initializes the game, parses input sets, and registers inputs.
Definition runner.hpp:98
void printInfo() const
Logs runner state information.
Definition runner.hpp:472
uint32_t _hashStepTolerance
Hash step tolerance, used to derive the hash-step-tolerance stage.
Definition runner.hpp:547
std::unique_ptr< Game > _game
The owned game instance driven by the runner.
Definition runner.hpp:545
uint32_t _historyShardId
This runner's contention-free free-list shard (its worker thread id).
Definition runner.hpp:555
jaffarPlus::InputSet::inputIndex_t getInputIndex(const std::string &input) const
Looks up the index registered for an input string.
Definition runner.hpp:274
std::map< InputSet::inputIndex_t, std::string > _inputStringMap
Maps an input index back to its input string.
Definition runner.hpp:568
Runner(std::unique_ptr< Game > &game, const nlohmann::json &config)
Constructs a runner that takes ownership of game and reads its settings from config.
Definition runner.hpp:49
std::vector< InputSet::inputIndex_t > getInputsFromInputSets(const std::vector< std::unique_ptr< InputSet > > &inputSets) const
Collects the input indexes of every input set whose conditions currently evaluate to true.
Definition runner.hpp:222
size_t getHistorySize() const
Returns the serialized size of the cold input-history "path", in bytes.
Definition runner.hpp:416
std::vector< std::unique_ptr< InputSet > > _allowedInputSets
Parsed allowed input sets.
Definition runner.hpp:594
static std::unique_ptr< Runner > getRunner(const nlohmann::json &emulatorConfig, const nlohmann::json &gameConfig, const nlohmann::json &runnerConfig)
Creates a runner from the emulator, game and runner configurations.
Definition runner.hpp:527
void advanceState(const InputSet::inputIndex_t inputIdx)
Advances the game by one input, then by the configured number of frameskip frames.
Definition runner.hpp:309
size_t _stepCount
Inputs applied so far (the state's depth).
Definition runner.hpp:552
const nlohmann::json & getInputHistoryConfig() const
The configured "Store Input History" object (used by the engine to build the shared backing).
Definition runner.hpp:142
void setSearchStep(const size_t searchStep)
Sets the step counter from a search step.
Definition runner.hpp:351
void setInputHistoryBacking(const std::shared_ptr< void > &backing, const uint32_t shardId, const uint32_t numShards)
Injects the shared input-history backing (e.g.
Definition runner.hpp:134
size_t _largestInputSetSize
Largest input set size detected (used for output formatting).
Definition runner.hpp:596
jaffarCommon::hash::hash_t computeHash() const
Computes a hash of the current runner state.
Definition runner.hpp:426
Game * getGame() const
Returns a pointer to the owned game instance.
Definition runner.hpp:516
std::vector< nlohmann::json > _allowedInputSetsJs
JSON descriptions of the allowed input sets (parsed at initialization).
Definition runner.hpp:588
std::map< jaffarCommon::hash::hash_t, InputSet::inputIndex_t > _inputHashMap
Maps an input string's hash to its index.
Definition runner.hpp:566
void serializeState(jaffarCommon::serializer::Base &serializer) const
Serializes the runner state: the game state, the input history, and the input counter.
Definition runner.hpp:360
std::string getInputHistoryString() const
Builds a newline-separated string of the recorded input history.
Definition runner.hpp:456
void deserializeHotState(jaffarCommon::deserializer::Base &deserializer)
Restores only the hot game+emulator state from deserializer.
Definition runner.hpp:400
std::string _frameskipCustomInput
The custom input string to apply on skipped frames.
Definition runner.hpp:578
bool isInitialized() const
Returns whether the runner has been initialized.
Definition runner.hpp:540
bool _frameskipUseCustomInput
Whether skipped frames use the custom input; false repeats the applied input.
Definition runner.hpp:576
void deserializeHistory(jaffarCommon::deserializer::Base &deserializer)
Restores only the cold input-history "path" from deserializer.
Definition runner.hpp:406
const auto getCandidateInputs() const
Returns the inputs currently allowed by the candidate input sets.
Definition runner.hpp:266
bool _bypassHashCalculation
Whether computeHash returns the game's direct hash instead of hashing via MetroHash128.
Definition runner.hpp:558
size_t getHotStateSize() const
Returns the serialized size of the hot game+emulator state, in bytes.
Definition runner.hpp:409
bool _testCandidateInputs
Whether candidate input sets are parsed and tested.
Definition runner.hpp:598
void serializeHistory(jaffarCommon::serializer::Base &serializer) const
Serializes only the cold input-history "path" (written once at state creation, read at solution time)...
Definition runner.hpp:404
InputHistory * getInputHistory() const
The input-history strategy in use (for the StateDb's per-slot manager operations).
Definition runner.hpp:145
uint32_t _historyNumShards
Shard count of the backing (engine: threadCount+1; standalone: 2).
Definition runner.hpp:556
bool isInputRegistered(const std::string &inputString)
Reports whether an input string has been registered.
Definition runner.hpp:292
void serializeHotState(jaffarCommon::serializer::Base &serializer) const
Serializes only the hot game+emulator state (what the search reads every step) into serializer.
Definition runner.hpp:398
void pushInput(const InputSet::inputIndex_t inputIdx)
Records an applied input into the input history at the current step, and advances the step counter.
Definition runner.hpp:338
InputSet::inputIndex_t _maxInputIndex
One past the highest registered input index; determines the input-history encoding width.
Definition runner.hpp:564
nlohmann::json _inputHistoryConfig
The "Store Input History" config object (selects None/Raw/Trie).
Definition runner.hpp:550
std::vector< nlohmann::json > _candidateInputSetsJs
JSON descriptions of the candidate input sets (parsed at initialization).
Definition runner.hpp:590
std::vector< std::unique_ptr< InputSet > > _candidateInputSets
Parsed candidate input sets.
Definition runner.hpp:592
void deserializeState(jaffarCommon::deserializer::Base &deserializer)
Restores the runner state: the game state, the input history, and the input counter.
Definition runner.hpp:372
size_t getStepCount() const
Returns the current step counter (number of inputs applied / the state's depth).
Definition runner.hpp:354
Abstract base for a JaffarPlus game: wraps an emulator, registers game properties,...
Builds the configured InputHistory strategy from the "Store Input History" config object.
A set of input indexes gated by conditions: the inputs become available only when all of the set's co...