-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathplayer.py
129 lines (102 loc) · 3.46 KB
/
player.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
from __future__ import annotations
from logging import getLogger
from card import YELLOW, Card
from errors import CanNotDiscardError, NotEnoughPlayersError, TooManyCardsError
class Player:
"""
This class represents a player.
It is basically a circular doubly-linked list.
On initialization, it will connect itself to a game and its
other players by placing itself behind the current player.
"""
prev: Player
next: Player
def __init__(self, game, user):
self.game = game
self.user = user
self.discard_amount = 0
self.cards = []
self.purple_cards = []
self.score = 0
self.logger = getLogger(__name__)
# Check if this player is the first player in this game.
if game.current_player:
self.next = game.current_player
self.prev = game.current_player.prev
game.current_player.prev.next = self
game.current_player.prev = self
else:
self.next = self
self.prev = self
game.current_player = self
@property
def left(self) -> Player:
return self.prev
@property
def right(self) -> Player:
return self.next
@property
def front(self) -> Player:
if len(self.game.players) < 4:
raise NotEnoughPlayersError()
if len(self.game.players) <= 7:
return self.next.next
return self.next.next.next
def draw_first_hand(self):
for _ in range(13):
self.cards.append(self.game.yellow_deck.draw())
def leave(self):
"""Removes player from the game and closes the gap in the list"""
if self.next is self:
return
self.next.prev = self.prev
self.prev.next = self.next
self.next = None
self.prev = None
self.cards = []
self.discard_amount = 0
def __repr__(self):
return repr(self.user)
def __str__(self):
return str(self.user)
def draw(self):
while len(self.cards) < 13:
self.cards.append(self.game.yellow_deck.draw())
def play(self, card: Card):
"""Plays a card and removes it from hand"""
if card.color == YELLOW:
if len(self.game.board.yellow[self]) >= self.game.board.purple.space:
raise TooManyCardsError()
self.cards.remove(card)
self.game.board.play_card_by(self, card)
def discard(self, card: Card):
"""Disacrd a card from the game
Args:
card (Card): A card object to discard
Raises:
CanNotDiscardError: When the discard_amount is equals to 0
"""
if self.discard_amount == 0:
raise CanNotDiscardError()
self.cards.remove(card)
@property
def discarded(self) -> bool:
"""A bool value to validate whether the cards are discarded.
Returns:
bool: Own cards equal to 13 - space of the purple card - discard amount
"""
return (
len(self.cards) == 13 - self.game.board.purple.space - self.discard_amount
)
@property
def can_play(self) -> bool:
"""Player can play a yellow card
Returns:
bool: [description]
"""
purple_card = self.game.board.purple
return (
self.game.current_player != self
and purple_card is not None
and purple_card.space > len(self.game.board.yellow[self])
)