Skip to main content
Run headless simulation of a replay and verify claimed statistics match actual results.

Usage

crimson replay verify <replay_file> [OPTIONS]

Arguments

replay_file
Path
required
Replay file path (.crd).If a filename is provided without path, also searches base-dir/replays/

Options

--max-ticks
int
Stop after N ticks.Default: Full replayUseful for partial verification or debugging.
--trace-rng
flag
Enable replay RNG trace mode during simulation.Records all RNG calls for debugging desync issues.
--format
human|json
default:"human"
Output format.
  • human — Human-readable text
  • json — Machine-readable JSON
--json-out
Path
Optional JSON output path for verify result payload.
--base-dir
Path
Base path for runtime files.Default: Per-user OS data directory
--runtime-dir
Path
Alias for --base-dir.

Output Format

Human Format (default)

crimson replay verify run.crd
Output:
ok: ticks=36000 elapsed_ms=600000 score_xp=125000 kills=1200 most_used_weapon_id=5 shots_fired=8500 shots_hit=6200 rng_state=0x12345678; header_claim complete=True match=True mismatches=-

JSON Format

crimson replay verify run.crd --format json
Output:
{
  "schema_version": 1,
  "status": "ok",
  "replay": "/path/to/run.crd",
  "replay_sha256": "abc123...",
  "run_result": {
    "game_mode_id": 1,
    "tick_rate": 60,
    "ticks": 36000,
    "elapsed_ms": 600000,
    "score_xp": 125000,
    "creature_kill_count": 1200,
    "most_used_weapon_id": 5,
    "shots_fired": 8500,
    "shots_hit": 6200,
    "rng_state": 305419896
  },
  "header_claim": {
    "expected": {
      "complete": true,
      "ticks": 36000,
      "elapsed_ms": 600000,
      "score_xp": 125000,
      "kills": 1200,
      "most_used_weapon_id": 5,
      "shots_fired": 8500,
      "shots_hit": 6200
    },
    "simulated": {
      "complete": true,
      "ticks": 36000,
      "elapsed_ms": 600000,
      "score_xp": 125000,
      "kills": 1200,
      "most_used_weapon_id": 5,
      "shots_fired": 8500,
      "shots_hit": 6200
    },
    "match": true,
    "mismatched_fields": []
  },
  "score_claim": null
}

Exit Codes

  • 0 — Success, all claims verified
  • 1 — Error (file not found, codec error, etc.)
  • 3 — Header stats mismatch (score/kills don’t match)

Verification Process

  1. Load Replay — Parse .crd file and validate structure
  2. Headless Simulation — Run game logic without rendering
  3. Compare Stats — Match simulated results against claimed header values
  4. Report — Output verification result

Verified Fields

When replay is complete (--max-ticks not used), verifies:
ticks
int
Total simulation ticks.
elapsed_ms
int
Game time in milliseconds.
score_xp
int
Final score / experience points.
kills
int
Total creature kills.
most_used_weapon_id
int
Weapon with most shots fired.
shots_fired
int
Total shots fired across all weapons.
shots_hit
int
Total shots that hit enemies.

Examples

Basic Verification

crimson replay verify survival-run.crd
Output:
ok: ticks=36000 elapsed_ms=600000 score_xp=125000 kills=1200 ...

Verify with JSON Output

crimson replay verify run.crd --format json --json-out result.json

Partial Verification

# Verify first 10000 ticks only
crimson replay verify run.crd --max-ticks 10000
Output:
ok: ticks=10000 elapsed_ms=166666 score_xp=42000 kills=400 ...
Partial verification skips header claim comparison.

Debug with RNG Tracing

crimson replay verify run.crd --trace-rng
Enables detailed RNG call logging for debugging desync issues.

Verify from Custom Directory

crimson replay verify /path/to/replay.crd

Batch Verification

for f in replays/*.crd; do
  echo "Verifying $f..."
  crimson replay verify "$f" --format json --json-out "results/$(basename $f .crd).json"
done

Error Handling

File Not Found

crimson replay verify missing.crd
Output:
replay file not found: ./missing.crd
Exit code: 1

Score Mismatch

crimson replay verify tampered.crd
Output:
header_stats_mismatch: ticks=36000 elapsed_ms=600000 score_xp=125000 kills=1200 ...; header_claim complete=True match=False mismatches=score_xp,kills
Exit code: 3

Version Incompatibility

crimson replay verify old-version.crd
Output:
replay verification failed: replay version 0.5.0 incompatible with current 0.7.0
Exit code: 1

Use Cases

Speedrun Verification

Verify claimed times and scores:
crimson replay verify speedrun.crd --format json > proof.json

Automated Testing

#!/bin/bash
if crimson replay verify test.crd --format json; then
  echo "Test passed"
else
  echo "Test failed"
  exit 1
fi

CI/CD Integration

# .github/workflows/verify-replays.yml
- name: Verify regression replays
  run: |
    for replay in tests/replays/*.crd; do
      crimson replay verify "$replay" --format json
    done

Leaderboard Validation

Validate submitted replay before accepting:
import subprocess
import json

result = subprocess.run(
    ["crimson", "replay", "verify", "submission.crd", "--format", "json"],
    capture_output=True,
    text=True,
)

if result.returncode == 0:
    data = json.loads(result.stdout)
    score = data["run_result"]["score_xp"]
    print(f"Valid submission: {score} points")
else:
    print("Invalid replay")

Performance

Headless verification is fast:
  • No rendering overhead
  • No asset loading
  • Pure simulation logic
  • Typical: 10-20x realtime speed
Example: 10-minute replay verifies in ~30-60 seconds.

SHA256 Integrity

The verification result includes replay file SHA256:
{
  "replay_sha256": "abc123..."
}
This ensures:
  • Replay file hasn’t been modified
  • Tamper detection
  • Cryptographic proof of authenticity

See Also

Build docs developers (and LLMs) love