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:
2026-07-01 19:20:08 +00:00
committed by mlangkabel
parent cf68ac2862
commit d74ba5bfad
40 changed files with 3385 additions and 129 deletions

View File

@@ -0,0 +1,40 @@
#pragma once
#include <QPoint>
#include "BuildingId.h"
#include "BuildingType.h"
#include "Rotation.h"
#include "Simulation.h"
class BeltSystem;
class BuildingSystem;
// Test-only backdoor to Simulation's private player-action mutators and mutable
// subsystem accessors. Declared a friend of Simulation, so it can hand tests the
// same mutation surface that Simulation::apply uses internally — without exposing
// those mutators to production (UI/app) code, which must go through the command
// chokepoint (docs/replay_design.md).
//
// This header lives under src/test and is not on the lib/ui/app include path, so
// only test translation units can reach it. Non-player test setup that has no
// command equivalent (e.g. placeImmediate, forEachBuilding buffer injection) is
// reached via buildings(sim)/belts(sim).
struct SimulationTestAccess
{
static BuildingSystem& buildings(Simulation& sim) { return sim.buildingsMutable(); }
static BeltSystem& belts(Simulation& sim) { return sim.beltsMutable(); }
static BuildingId place(Simulation& sim, BuildingType type, QPoint anchor,
Rotation rotation)
{
return sim.tryPlaceBuilding(type, anchor, rotation);
}
static void demolish(Simulation& sim, BuildingId id) { sim.demolish(id); }
static void applySchematicChoice(Simulation& sim, int choiceIndex)
{
sim.applySchematicChoice(choiceIndex);
}
};