eleusis / cards.py
nph4rd's picture
Eleusis: play the benchmark rules against rl4-step30 recorded games (static + Pyodide)
acd049c verified
Raw
History Blame Contribute Delete
2.17 kB
from __future__ import annotations
from dataclasses import dataclass
SUITS: dict[str, tuple[str, str]] = {
"H": ("hearts", "red"),
"D": ("diamonds", "red"),
"C": ("clubs", "black"),
"S": ("spades", "black"),
}
RANK_LABELS = ("A", "2", "3", "4", "5", "6", "7", "8", "9", "10", "J", "Q", "K")
RANK_VALUES = {
label: index + 1
for index, label in enumerate(RANK_LABELS)
}
@dataclass(frozen=True)
class Card:
symbol: str
suit: str
suit_symbol: str
color: str
rank: int
rank_label: str
@property
def is_ace(self) -> bool:
return self.rank == 1
@property
def is_face(self) -> bool:
return self.rank in {11, 12, 13}
def __str__(self) -> str:
return self.symbol
def __contains__(self, value: object) -> bool:
return str(value) in self.symbol
def __getitem__(self, index: int | slice) -> str:
return self.symbol[index]
def __iter__(self):
return iter(self.symbol)
def __len__(self) -> int:
return len(self.symbol)
def count(self, value: str) -> int:
return self.symbol.count(value)
def index(self, value: str) -> int:
return self.symbol.index(value)
def startswith(self, prefix: str) -> bool:
return self.symbol.startswith(prefix)
def endswith(self, suffix: str) -> bool:
return self.symbol.endswith(suffix)
def deck() -> list[str]:
return [f"{rank}{suit}" for suit in SUITS for rank in RANK_LABELS]
def parse_card(symbol: str) -> Card:
normalized = str(symbol or "").strip().upper()
if len(normalized) < 2:
raise ValueError(f"Unknown card: {symbol}")
suit_symbol = normalized[-1]
rank_label = normalized[:-1]
if suit_symbol not in SUITS:
raise ValueError(f"Unknown card suit: {symbol}")
if rank_label not in RANK_VALUES:
raise ValueError(f"Unknown card rank: {symbol}")
suit, color = SUITS[suit_symbol]
return Card(
symbol=f"{rank_label}{suit_symbol}",
suit=suit,
suit_symbol=suit_symbol,
color=color,
rank=RANK_VALUES[rank_label],
rank_label=rank_label,
)