138 lines
3.3 KiB
Python
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
|
|
),
|
|
))
|