Source code for pyscoundrel.models.room

"""Room model for PyScoundrel."""

from dataclasses import dataclass, field
from typing import List, Optional

from .card import Card


[docs] @dataclass class Room: """ A room in the dungeon containing 4 cards. Players must face 3 of the 4 cards, leaving 1 for the next room. """ cards: List[Card] = field(default_factory=list) cards_faced: List[Card] = field(default_factory=list)
[docs] def add_card(self, card: Card) -> None: """ Add a card to the room. Args: card: Card to add """ if len(self.cards) >= 4: raise ValueError("Room already has 4 cards!") self.cards.append(card)
[docs] def face_card(self, index: int) -> Card: """ Face a card from the room by index. Args: index: Index of card to face (0-3) Returns: The faced card Raises: IndexError: If index is invalid ValueError: If trying to face more than 3 cards or card already faced """ if len(self.cards_faced) >= 3: raise ValueError("Cannot face more than 3 cards per room!") if index < 0 or index >= len(self.cards): raise IndexError(f"Invalid card index: {index}") card = self.cards[index] # Check if this card has already been faced if card in self.cards_faced: raise ValueError(f"Card at index {index} has already been faced!") self.cards_faced.append(card) return card
[docs] def get_remaining_card(self) -> Optional[Card]: """ Get the one remaining card that wasn't faced. Returns: The remaining card, or None if not exactly 1 card remains """ if len(self.cards_faced) != 3: return None for card in self.cards: if card not in self.cards_faced: return card return None
@property def is_full(self) -> bool: """Check if room has 4 cards.""" return len(self.cards) == 4 @property def is_complete(self) -> bool: """Check if 3 cards have been faced.""" return len(self.cards_faced) == 3 @property def available_cards(self) -> List[Card]: """Get list of cards that haven't been faced yet.""" return [c for c in self.cards if c not in self.cards_faced] @property def num_cards_remaining(self) -> int: """Get number of cards not yet faced.""" return len(self.cards) - len(self.cards_faced) def __str__(self) -> str: card_strs = [] for i, card in enumerate(self.cards): if card in self.cards_faced: card_strs.append(f"[{card.display_name}]") else: card_strs.append(card.display_name) return f"Room: {' '.join(card_strs)}" def __repr__(self) -> str: return f"Room(cards={len(self.cards)}, faced={len(self.cards_faced)})"