Skip to content

Commit 2b315c3

Browse files
Forcing repetition of inputs
1 parent 98354b2 commit 2b315c3

File tree

2 files changed

+58
-9
lines changed

2 files changed

+58
-9
lines changed

examples/nes/marbleMadness/stage01.jaffar

+6-4
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717
"Max Store Size (Mb)": 40000
1818
},
1919
"State Database": {
20-
"Max Size (Mb)": 300000
20+
"Max Size (Mb)": 10000
2121
}
2222
},
2323
"Emulator Configuration": {
@@ -42,15 +42,17 @@
4242
"Frameskip Rate": 0,
4343
"Hash Step Tolerance": 0,
4444
"Show Empty Input Slots": true,
45-
"Show Allowed Inputs": false,
45+
"Show Allowed Inputs": true,
4646
"Bypass Hash Calculation": false,
4747
"Store Input History": {
4848
"Enabled": true,
4949
"Max Size": 370
5050
},
5151
"Allowed Input Sets": [
5252
{
53-
"Conditions": [],
53+
"Conditions": [
54+
{ "Property": "Try New Inputs", "Op": "==", "Value": true }
55+
],
5456
"Inputs": [
5557
"|..|U......A|",
5658
"|..|.D.....A|",
@@ -72,7 +74,7 @@
7274
"Frame Rate": 60.1,
7375
"Last Input Step Reward": 0.0,
7476
"Trace File Path": "jaffar.trace",
75-
"Keep Last Input Length": 2,
77+
"Repeat Prev Input Times": 4,
7678
"Print Properties": [
7779
"Marble Pos X",
7880
"Marble Pos Y",

games/nes/marbleMadness.hpp

+52-5
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,9 @@ class MarbleMadness final : public jaffarPlus::Game
2525
// Parsing configuration
2626
_lastInputStepReward = jaffarCommon::json::getNumber<float>(config, "Last Input Step Reward");
2727

28+
// Getting setting for the repetition of the previous input
29+
_repeatPrevInputCount = jaffarCommon::json::getNumber<uint16_t>(config, "Repeat Prev Input Times");
30+
2831
// Getting emulator name (for runtime use)
2932
_traceFilePath = jaffarCommon::json::getString(config, "Trace File Path");
3033

@@ -83,6 +86,7 @@ class MarbleMadness final : public jaffarPlus::Game
8386
registerGameProperty("Marble Pos X", &_marblePosX, Property::datatype_t::dt_float32, Property::endianness_t::little);
8487
registerGameProperty("Marble Pos Y", &_marblePosY, Property::datatype_t::dt_float32, Property::endianness_t::little);
8588
registerGameProperty("Marble Pos Z", &_marblePosZ, Property::datatype_t::dt_float32, Property::endianness_t::little);
89+
registerGameProperty("Try New Inputs", &_tryNewInputs, Property::datatype_t::dt_bool, Property::endianness_t::little);
8690

8791
_gameTimer = (uint8_t*)_propertyMap[jaffarCommon::hash::hashString("Game Timer" )]->getPointer();
8892
_gameCycle = (uint8_t*)_propertyMap[jaffarCommon::hash::hashString("Game Cycle" )]->getPointer();
@@ -104,13 +108,29 @@ class MarbleMadness final : public jaffarPlus::Game
104108

105109
// Getting index for a non input
106110
_nullInputIdx = _emulator->registerInput("|..|........|");
111+
112+
// Initializing prev input values
113+
_prevInputIdx = _nullInputIdx;
114+
_prevInputRepeatedTimes = 0;
115+
_tryNewInputs = true;
107116
}
108117

109118
__INLINE__ void advanceStateImpl(const InputSet::inputIndex_t input) override
110119
{
111120
// Increasing counter if input is null
112121
if (input != _nullInputIdx) _lastInputStep = _currentStep;
113122

123+
// Checking input repetition
124+
if (_prevInputIdx == input) _prevInputRepeatedTimes++;
125+
else _prevInputRepeatedTimes = 0;
126+
127+
// Checking if next time we need to try new inputs
128+
if (_prevInputRepeatedTimes >= _repeatPrevInputCount) _tryNewInputs = true;
129+
else _tryNewInputs = false;
130+
131+
// Remembering input
132+
_prevInputIdx = input;
133+
114134
// Running emulator
115135
_emulator->advanceState(input);
116136

@@ -175,14 +195,20 @@ class MarbleMadness final : public jaffarPlus::Game
175195

176196
__INLINE__ void serializeStateImpl(jaffarCommon::serializer::Base& serializer) const override
177197
{
178-
serializer.pushContiguous(&_lastInputStep, sizeof(_lastInputStep));
179-
serializer.pushContiguous(&_currentStep, sizeof(_currentStep));
198+
serializer.push(&_lastInputStep, sizeof(_lastInputStep));
199+
serializer.push(&_currentStep, sizeof(_currentStep));
200+
serializer.push(&_prevInputIdx, sizeof(_prevInputIdx));
201+
serializer.push(&_prevInputRepeatedTimes, sizeof(_prevInputRepeatedTimes));
202+
serializer.push(&_tryNewInputs, sizeof(_tryNewInputs));
180203
}
181204

182205
__INLINE__ void deserializeStateImpl(jaffarCommon::deserializer::Base& deserializer)
183206
{
184-
deserializer.popContiguous(&_lastInputStep, sizeof(_lastInputStep));
185-
deserializer.popContiguous(&_currentStep, sizeof(_currentStep));
207+
deserializer.pop(&_lastInputStep, sizeof(_lastInputStep));
208+
deserializer.pop(&_currentStep, sizeof(_currentStep));
209+
deserializer.pop(&_prevInputIdx, sizeof(_prevInputIdx));
210+
deserializer.pop(&_prevInputRepeatedTimes, sizeof(_prevInputRepeatedTimes));
211+
deserializer.pop(&_tryNewInputs, sizeof(_tryNewInputs));
186212
}
187213

188214
__INLINE__ float calculateGameSpecificReward() const
@@ -220,6 +246,9 @@ class MarbleMadness final : public jaffarPlus::Game
220246
jaffarCommon::logger::log("[Jaffar] + Marble Airtime: %02u\n", *_marbleAirtime);
221247
jaffarCommon::logger::log("[Jaffar] + Marble Surface Angle: %02u\n", *_marbleSurfaceAngle);
222248

249+
jaffarCommon::logger::log("[Jaffar] + Prev Input: %02u\n", _prevInputIdx);
250+
jaffarCommon::logger::log("[Jaffar] + Prev Input Repetitions: %02u / %02u (Try new: %s)\n", _prevInputRepeatedTimes, _repeatPrevInputCount, _tryNewInputs ? "Yes" : "No" );
251+
223252
if (std::abs(_pointMagnet.intensity) > 0.0f)
224253
{
225254
jaffarCommon::logger::log("[J+] + Point Magnet Intensity: %.5f, X: %3.3f, Y: %3.3f\n", _pointMagnet.intensity, _pointMagnet.x, _pointMagnet.y);
@@ -298,6 +327,11 @@ class MarbleMadness final : public jaffarPlus::Game
298327
bool _isDumpingTrace = false;
299328
std::string _traceDumpString;
300329

330+
__INLINE__ void getAdditionalAllowedInputs(std::vector<InputSet::inputIndex_t>& allowedInputSet) override
331+
{
332+
if (_tryNewInputs == false) allowedInputSet.push_back(_prevInputIdx);
333+
}
334+
301335
__INLINE__ void playerPrintCommands() const override
302336
{
303337
jaffarCommon::logger::log("[J+] t: start/stop trace dumping (%s)\n", _isDumpingTrace ? "On" : "Off");
@@ -307,7 +341,7 @@ class MarbleMadness final : public jaffarPlus::Game
307341
{
308342
// If storing a trace, do it here
309343
if (_isDumpingTrace == true) _traceDumpString += std::to_string(_marblePosX) + std::string(" ") + std::to_string(_marblePosY) + std::string("\n");
310-
344+
311345
if (command == 't')
312346
{
313347
if (_isDumpingTrace == false)
@@ -393,6 +427,19 @@ class MarbleMadness final : public jaffarPlus::Game
393427
float _traceDistanceX;
394428
float _traceDistanceY;
395429
float _traceDistance;
430+
431+
// What was the prev input
432+
InputSet::inputIndex_t _prevInputIdx;
433+
434+
// How many times the prev input is repeated
435+
uint16_t _prevInputRepeatedTimes;
436+
437+
// How many times to repeat the prev input for
438+
uint16_t _repeatPrevInputCount;
439+
440+
// Flag that indicates whether the engine should try all possible inputs
441+
bool _tryNewInputs;
442+
396443
};
397444

398445
} // namespace nes

0 commit comments

Comments
 (0)