Normalized, arena-agnostic playback payload. The player shell only relies on ``w``, ``h``, ``frames`` (each frame carrying a ``turn``), ``winner`` and ``draw``. Everything an arena's ``DRAW_JS`` additionally needs (colors, team names, walls, max health, ...) rides along in ``extra`` and
| 27 | |
| 28 | @dataclass |
| 29 | class ReplayData: |
| 30 | """Normalized, arena-agnostic playback payload. |
| 31 | |
| 32 | The player shell only relies on ``w``, ``h``, ``frames`` (each frame carrying a |
| 33 | ``turn``), ``winner`` and ``draw``. Everything an arena's ``DRAW_JS`` additionally |
| 34 | needs (colors, team names, walls, max health, ...) rides along in ``extra`` and is |
| 35 | merged into the JS ``G`` object. |
| 36 | """ |
| 37 | |
| 38 | w: int |
| 39 | h: int |
| 40 | frames: list[dict] |
| 41 | winner: str | None = None |
| 42 | draw: bool = False |
| 43 | extra: dict = field(default_factory=dict) |
| 44 | |
| 45 | @property |
| 46 | def payload(self) -> dict: |
| 47 | """The ``G`` object handed to the JS player.""" |
| 48 | return {"w": self.w, "h": self.h, "frames": self.frames, "winner": self.winner, "draw": self.draw, **self.extra} |
| 49 | |
| 50 | def __bool__(self) -> bool: # truthy iff it actually has frames to play |
| 51 | return bool(self.frames) |
| 52 | |
| 53 | |
| 54 | @dataclass |