Add match replay and JSONL export

This commit is contained in:
2026-07-12 15:14:24 +09:00
parent 7e481ca064
commit f854d97764
6 changed files with 616 additions and 141 deletions
@@ -0,0 +1,42 @@
# Lost Cities Match Record v1
Last verified: 2026-07-12
`coolrl.lost-cities.match.v1` is the canonical portable record for one complete
or in-progress classic Lost Cities match. Files use UTF-8 JSON Lines (`.jsonl`)
so metadata can be inspected without loading the full replay and steps can be
streamed in order.
## Row 1: metadata
The first row has `type: "metadata"` and `format:
"coolrl.lost-cities.match.v1"`. It records creation time, classic rules,
initial seed, human seat, opponent identity, and completion status. Producers
may add fields; v1 readers must ignore unknown metadata fields.
## Rows 2+: steps
Every remaining row has `type: "step"` and a contiguous zero-based `index`.
Step 0 is the initial position and has null `actor`, `phase_before`, and
`action_id`. Later steps contain:
- `actor`: player that took the action (`0` or `1`).
- `phase_before`: `card` or `draw`.
- `action_id`: the classic engine unified action ID.
- `state`: complete `GameState.to_snapshot()` output after the action.
- `public_hands`: cards known to be in each player's hand because they were
drawn from a discard pile. Entries use `{color, value, count}`; wagers have
value 0 and numbered cards use their printed value.
Full state snapshots intentionally include hidden hands and deck order. A match
record is therefore suitable for post-game analysis and deterministic replay,
but must not be exposed to a player during a live match.
## Compatibility
Readers must reject an unknown `format` value rather than guessing. New
optional fields may be added within v1. Any incompatible change to action IDs,
state encoding, or required row semantics requires `v2`.
The reference reader, writer, and validator are in
`src/coolrl_lost_cities/games/classic/match_record.py`.