@@ -25,6 +25,9 @@ class MarbleMadness final : public jaffarPlus::Game
25
25
// Parsing configuration
26
26
_lastInputStepReward = jaffarCommon::json::getNumber<float >(config, " Last Input Step Reward" );
27
27
28
+ // Getting setting for the repetition of the previous input
29
+ _repeatPrevInputCount = jaffarCommon::json::getNumber<uint16_t >(config, " Repeat Prev Input Times" );
30
+
28
31
// Getting emulator name (for runtime use)
29
32
_traceFilePath = jaffarCommon::json::getString (config, " Trace File Path" );
30
33
@@ -83,6 +86,7 @@ class MarbleMadness final : public jaffarPlus::Game
83
86
registerGameProperty (" Marble Pos X" , &_marblePosX, Property::datatype_t ::dt_float32, Property::endianness_t ::little);
84
87
registerGameProperty (" Marble Pos Y" , &_marblePosY, Property::datatype_t ::dt_float32, Property::endianness_t ::little);
85
88
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);
86
90
87
91
_gameTimer = (uint8_t *)_propertyMap[jaffarCommon::hash::hashString (" Game Timer" )]->getPointer ();
88
92
_gameCycle = (uint8_t *)_propertyMap[jaffarCommon::hash::hashString (" Game Cycle" )]->getPointer ();
@@ -104,13 +108,29 @@ class MarbleMadness final : public jaffarPlus::Game
104
108
105
109
// Getting index for a non input
106
110
_nullInputIdx = _emulator->registerInput (" |..|........|" );
111
+
112
+ // Initializing prev input values
113
+ _prevInputIdx = _nullInputIdx;
114
+ _prevInputRepeatedTimes = 0 ;
115
+ _tryNewInputs = true ;
107
116
}
108
117
109
118
__INLINE__ void advanceStateImpl (const InputSet::inputIndex_t input) override
110
119
{
111
120
// Increasing counter if input is null
112
121
if (input != _nullInputIdx) _lastInputStep = _currentStep;
113
122
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
+
114
134
// Running emulator
115
135
_emulator->advanceState (input);
116
136
@@ -175,14 +195,20 @@ class MarbleMadness final : public jaffarPlus::Game
175
195
176
196
__INLINE__ void serializeStateImpl (jaffarCommon::serializer::Base& serializer) const override
177
197
{
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));
180
203
}
181
204
182
205
__INLINE__ void deserializeStateImpl (jaffarCommon::deserializer::Base& deserializer)
183
206
{
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));
186
212
}
187
213
188
214
__INLINE__ float calculateGameSpecificReward () const
@@ -220,6 +246,9 @@ class MarbleMadness final : public jaffarPlus::Game
220
246
jaffarCommon::logger::log (" [Jaffar] + Marble Airtime: %02u\n " , *_marbleAirtime);
221
247
jaffarCommon::logger::log (" [Jaffar] + Marble Surface Angle: %02u\n " , *_marbleSurfaceAngle);
222
248
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
+
223
252
if (std::abs (_pointMagnet.intensity ) > 0 .0f )
224
253
{
225
254
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
298
327
bool _isDumpingTrace = false ;
299
328
std::string _traceDumpString;
300
329
330
+ __INLINE__ void getAdditionalAllowedInputs (std::vector<InputSet::inputIndex_t>& allowedInputSet) override
331
+ {
332
+ if (_tryNewInputs == false ) allowedInputSet.push_back (_prevInputIdx);
333
+ }
334
+
301
335
__INLINE__ void playerPrintCommands () const override
302
336
{
303
337
jaffarCommon::logger::log (" [J+] t: start/stop trace dumping (%s)\n " , _isDumpingTrace ? " On" : " Off" );
@@ -307,7 +341,7 @@ class MarbleMadness final : public jaffarPlus::Game
307
341
{
308
342
// If storing a trace, do it here
309
343
if (_isDumpingTrace == true ) _traceDumpString += std::to_string (_marblePosX) + std::string (" " ) + std::to_string (_marblePosY) + std::string (" \n " );
310
-
344
+
311
345
if (command == ' t' )
312
346
{
313
347
if (_isDumpingTrace == false )
@@ -393,6 +427,19 @@ class MarbleMadness final : public jaffarPlus::Game
393
427
float _traceDistanceX;
394
428
float _traceDistanceY;
395
429
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
+
396
443
};
397
444
398
445
} // namespace nes
0 commit comments