cardy/cardy/phase_10.py

138 lines
3.3 KiB
Python

from dataclasses import dataclass
from itertools import product
from typing import Any
from typing import Dict
from typing import List
from typing import Optional
from cardy.deck import Card
from cardy.deck import FaceUpPile
from cardy.deck import OpenCardSet
from cardy.deck import Pile
from cardy.deck import WildCard
from cardy.player import Player
class Phase10Card(Card):
pass
class Skip(Phase10Card):
pass
class Wild(WildCard, Phase10Card):
pass
class Deck(Pile):
def __init__(self):
cards: List[Phase10Card] = []
for c in product(range(1, 13), ("red", "blue", "green", "yellow")):
cards.append(Phase10Card(c[0], color=c[1]))
super().__init__(cards)
class PhaseSet(OpenCardSet):
pass
class Phase10Player(Player):
_table: List[FaceUpPile]
def __init__(self, name):
self._table = []
super().__init__(name)
def take_turn(self) -> Any:
pass
def __str__(self):
table = " no sets played"
if self._table:
table = "\n".join((" "+str(s) for s in self._table))
return "\n".join((
f"{self.name}: {len(self._hand)} in hand",
"On table:",
table,
))
def json(self, is_owner: bool=False) -> Dict[str, Any]:
state = {
"table": [pile.json() for pile in self._table],
}
if is_owner:
state["hand"] = [card.json() for card in self._hand]
if is_owner:
state["hand"] = len(self._hand)
@dataclass
class Phase10Turn:
player: Player
draw_card: bool
discard_card: Optional[Card]
play_sets: Optional[List[PhaseSet]]
play_on_sets: Optional[Dict[str, List[Card]]]
class Game(object):
_dealer_index: int
draw_pile: Deck
discard_pile: FaceUpPile
turn: int
game_round: int
players: List[Phase10Player]
sets: List[OpenCardSet]
def __init__(self, player_names: List[str]):
self._dealer_index = 0
self.turn = 1
self.game_round = 1
self.players = [Phase10Player(name) for name in player_names]
self.draw_pile = Deck()
self.draw_pile.shuffle()
self.discard_pile = FaceUpPile()
self.sets = []
def deal(self):
# each player draws 10
for _ in range(0, 10):
for seat in range(0, len(self.players)):
draw_seat = seat + self._dealer_index + 1
p = self.players[draw_seat % len(self.players)]
p.draw_cards(self.draw_pile)
def take_turn(self):
end_round = self.next_player.take_turn()
self.turn += 1
if end_round:
self._reset_round()
@property
def next_player(self) -> Player:
return self.players[self.turn % len(self.players)]
@property
def dealer(self) -> Player:
return self.players[self._dealer_index]
def _reset_round(self):
self.draw_pile = Deck()
self.draw_pile.shuffle()
self.dealer += 1
self.deal()
def __str__(self) -> str:
return "\n".join((
"Game",
f"Draw: {str(self.draw_pile)}",
f"Discard: {str(self.discard_pile)}",
"",
"\n\n".join(
str(p) for p in self.players
),
))