-
Notifications
You must be signed in to change notification settings - Fork 16
/
cards.py
145 lines (118 loc) · 4.17 KB
/
cards.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
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
import random
SUITS = ['hearts', 'spades', 'clubs', 'diamonds']
RANKS = ['ace', 2, 3, 4, 5, 6, 7, 8, 9, 10, 'jack', 'queen', 'king']
class Card:
"""Playing card to be used to fill a baccarat shoe and
to be drawn to a playing hand.
Args:
rank: int or string, the rank of the card.
suit: string, the suit of the card.
Attributes:
value: int, baccarat value of the card.
rank: int or string, the rank of the card.
suit: string, the suit of the card.
Raises:
ValueError: On invalid card rank or suit.
"""
def __init__(self, rank, suit):
if rank not in RANKS:
raise ValueError('Invalid card rank.')
if suit not in SUITS:
raise ValueError('Invalid card suit.')
self._rank = rank
self._suit = suit
self._value = self._rank if self._rank in range(2, 10) \
else 1 if self._rank == 'ace' \
else 0
@property
def value(self):
"""Get card value."""
return self._value
@property
def rank(self):
"""Get card rank."""
return self._rank
@property
def suit(self):
"""Get card suit."""
return self._suit
def __add__(self, other):
return (self._value + other) % 10
__radd__ = __add__
def __repr__(self):
"""Return the representation string as if the object was
called when creating a new instance.
"""
if isinstance(self._rank, str):
return f'Card(\'{self._rank}\', \'{self._suit}\')'
elif isinstance(self._rank, int):
return f'Card({self._rank}, \'{self._suit}\')'
def __str__(self):
"""Return a string with the rank and suit of the card."""
return f'{self._rank} of {self._suit}'
class Shoe:
"""Shoe with num_decks shuffled decks. All cards used in the game
will be drawn from this set.
Args:
num_decks: int, number of decks on the shoe.
Attributes:
num_decks: int, number of decks on the shoe.
cards: list, all the instances of the object PlayinCard
on the Shoe object.
Raises:
TypeError: If the num_decks is not an integer.
ValueError: If the num_decks is not positive.
"""
def __init__(self, num_decks):
if not isinstance(num_decks, int):
raise TypeError('Number of decks must be an integer.')
elif num_decks < 1:
raise ValueError('Number of decks must be positive.')
self._num_decks = num_decks
self._cards = []
self.add_decks()
@property
def num_decks(self):
"""Returns initial number of decks of shoe."""
return self._num_decks
@property
def num_cards(self):
"""Returns current number of cards in shoe."""
return len(self._cards)
@property
def cards(self):
"""Returns current list of cards in shoe."""
return self._cards
def add_decks(self, num_decks=None):
"""Refils the shoe with decks. Uses self.num_decks value if empty."""
if not num_decks:
num_decks = self._num_decks
for i in range(num_decks):
for suit in SUITS:
for rank in RANKS:
self._cards.append(Card(rank, suit))
random.shuffle(self._cards)
def draw_cards(self, num_cards):
"""Draws cards from shoe. Refills the shoe when
it is empty.
Args:
num_cards: int, number of cards to be drawn.
Returns:
cards_drawn: list, cards drawn from shoe.
"""
cards_drawn = []
for i in range(num_cards):
if len(self._cards) == 0:
self.add_decks()
cards_drawn.append(self._cards.pop())
return cards_drawn
def __repr__(self):
"""Return the representation string as if the object was
called when creating a new instance.
"""
return f'Shoe({self._num_decks})'
def __str__(self):
"""Returns a string with the number of decks and the
number of cards left.
"""
return f'{self._num_decks} decks shoe. {len(self._cards)} cards left.'