Replay: deterministic record & playback (#4)
Add deterministic record/playback for a run. Recording captures `(seed, config hash, ordered tick-tagged commands)` and re-simulates on playback — no state snapshots. `DotaFactory.exe --replay <file>` re-plays a recorded run view-only with manual speed/pause. Reviewed-on: #4 Co-authored-by: Malte Langkabel <malte.langkabel@gmail.com> Co-committed-by: Malte Langkabel <malte.langkabel@gmail.com>
This commit was merged in pull request #4.
This commit is contained in:
56
src/lib/sim/ReplayPlayer.cpp
Normal file
56
src/lib/sim/ReplayPlayer.cpp
Normal file
@@ -0,0 +1,56 @@
|
||||
#include "ReplayPlayer.h"
|
||||
|
||||
#include <utility>
|
||||
|
||||
#include "Command.h"
|
||||
#include "Simulation.h"
|
||||
|
||||
ReplayPlayer::ReplayPlayer(Simulation& simulation, std::vector<ReplayEntry> entries)
|
||||
: m_simulation(simulation)
|
||||
, m_entries(std::move(entries))
|
||||
{
|
||||
}
|
||||
|
||||
void ReplayPlayer::start()
|
||||
{
|
||||
processEntriesAt(0);
|
||||
}
|
||||
|
||||
void ReplayPlayer::advanceTo(Tick tick)
|
||||
{
|
||||
processEntriesAt(tick);
|
||||
}
|
||||
|
||||
bool ReplayPlayer::isFinished() const
|
||||
{
|
||||
return m_desyncTick.has_value() || m_cursor >= m_entries.size();
|
||||
}
|
||||
|
||||
std::optional<Tick> ReplayPlayer::getDesyncTick() const
|
||||
{
|
||||
return m_desyncTick;
|
||||
}
|
||||
|
||||
void ReplayPlayer::processEntriesAt(Tick tick)
|
||||
{
|
||||
// Consume entries for this tick in file order. The recording writes, at a
|
||||
// given tick: the periodic checksum (if any) first, then command lines each
|
||||
// followed by their post-apply checksum — so applying/verifying in file order
|
||||
// reproduces the original sequence exactly.
|
||||
while (!m_desyncTick.has_value()
|
||||
&& m_cursor < m_entries.size()
|
||||
&& m_entries[m_cursor].tick == tick)
|
||||
{
|
||||
const ReplayEntry& entry = m_entries[m_cursor];
|
||||
++m_cursor;
|
||||
|
||||
if (entry.isCommand)
|
||||
{
|
||||
m_simulation.apply(*entry.command);
|
||||
}
|
||||
else if (m_simulation.rngFingerprint() != entry.fingerprint)
|
||||
{
|
||||
m_desyncTick = tick;
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user