first prototype
This commit is contained in:
@@ -0,0 +1,73 @@
|
||||
"""Actions a player can take and their (de)serialization.
|
||||
|
||||
Actions are serialized as small JSON objects which are shared by the web
|
||||
frontend, the game server and the AI player:
|
||||
|
||||
- ``{"type": "bid", "value": 2}``
|
||||
- ``{"type": "play", "card": 17}``
|
||||
- ``{"type": "trump", "suit": "red"}``
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
from dataclasses import dataclass
|
||||
from typing import Any
|
||||
|
||||
from .cards import Card, Suit, card_by_id
|
||||
|
||||
|
||||
@dataclass(frozen=True, slots=True)
|
||||
class Bid:
|
||||
value: int
|
||||
|
||||
def to_dict(self) -> dict:
|
||||
return {"type": "bid", "value": self.value}
|
||||
|
||||
|
||||
@dataclass(frozen=True, slots=True)
|
||||
class PlayCard:
|
||||
card: Card
|
||||
|
||||
def to_dict(self) -> dict:
|
||||
return {"type": "play", "card": self.card.id}
|
||||
|
||||
|
||||
@dataclass(frozen=True, slots=True)
|
||||
class ChooseTrump:
|
||||
suit: Suit
|
||||
|
||||
def to_dict(self) -> dict:
|
||||
return {"type": "trump", "suit": self.suit.value}
|
||||
|
||||
|
||||
Action = Bid | PlayCard | ChooseTrump
|
||||
|
||||
|
||||
def action_to_dict(action: Action) -> dict:
|
||||
return action.to_dict()
|
||||
|
||||
|
||||
def action_from_dict(data: dict[str, Any]) -> Action:
|
||||
"""Parse an action from its JSON representation.
|
||||
|
||||
Raises ``ValueError`` if the data is malformed.
|
||||
"""
|
||||
if not isinstance(data, dict):
|
||||
raise ValueError("Action must be an object")
|
||||
kind = data.get("type")
|
||||
try:
|
||||
if kind == "bid":
|
||||
value = data["value"]
|
||||
if not isinstance(value, int) or isinstance(value, bool):
|
||||
raise ValueError("Bid value must be an integer")
|
||||
return Bid(value)
|
||||
if kind == "play":
|
||||
card_id = data["card"]
|
||||
if not isinstance(card_id, int) or isinstance(card_id, bool):
|
||||
raise ValueError("Card must be an integer id")
|
||||
return PlayCard(card_by_id(card_id))
|
||||
if kind == "trump":
|
||||
return ChooseTrump(Suit(data["suit"]))
|
||||
except KeyError as exc:
|
||||
raise ValueError(f"Missing field {exc} in action") from exc
|
||||
raise ValueError(f"Unknown action type: {kind!r}")
|
||||
Reference in New Issue
Block a user