1
0
Fork 0
mirror of synced 2024-05-19 12:02:29 +12:00
Bonfire/utils/cards.py

189 lines
5 KiB
Python

import random
from enum import IntEnum, auto
class Suit(IntEnum):
clubs = auto()
hearts = auto()
diamonds = auto()
spades = auto()
class Face(IntEnum):
ace = auto()
two = auto()
three = auto()
four = auto()
five = auto()
six = auto()
seven = auto()
eight = auto()
nine = auto()
ten = auto()
jack = auto()
queen = auto()
king = auto()
class Deck:
def __init__(self, prefill=True, ace_high=True, spades_high=False):
self.deck = []
if prefill:
self.refresh()
self.ace_high = ace_high
self.spades_high = spades_high
def __iter__(self):
for card in self.deck:
yield card
def __getitem__(self, key):
return self.deck[key]
def refresh(self):
"""A method that 'restarts' the deck, filling it back with 52 cards"""
self.deck = []
for _suit in Suit:
for _face in Face:
self.insert(Card(_suit, _face, self))
@property
def count(self):
"""A property to provide how many cards are currently in the deck"""
return len(self.deck)
@property
def empty(self):
"""A property to determine whether or not the deck has cards in it"""
return len(self.deck) == 0
def draw(self, count=1):
"""Generator to draw from the deck"""
try:
for i in range(count):
yield self.deck.pop()
except IndexError:
yield None
def insert(self, cards):
"""Adds the provided cards to the end of the deck"""
try:
self.deck.extend(cards)
for card in cards:
card._deck = self
except TypeError:
self.deck.append(cards)
cards._deck = self
def index(self, card):
"""Returns the index of the card provided (-1 if card is not in the deck)"""
return self.deck.index(card)
def pluck(self, index=None, card=None):
"""Pulls the provided card from the deck"""
if index:
return self.deck.pop(index)
elif card:
return self.deck.pop(self.index(card))
def shuffle(self):
"""Shuffles the deck in place"""
random.SystemRandom().shuffle(self.deck)
def get_card(self, suit, face):
"""Returns the provided card in the deck"""
for card in self.deck:
if card.suit == suit and card.value == face:
return card
class Card:
"""The class that holds all the details for a card in the deck"""
def __init__(self, suit, value, deck):
self._suit = suit
self._value = value
self._deck = deck
@property
def suit(self):
"""The suit (club, diamond, heart, spade)"""
return self._suit
@property
def value(self):
"""The face value (2-10, J, Q, K, A)"""
return self._value
@property
def face_short(self):
"""The first 'letter' of the face, (2-10 will be the numbers)"""
if self.value == Face.ace or \
self.value == Face.jack or \
self.value == Face.queen or \
self.value == Face.king:
return self.value.name[0]
else:
return self.value.value
def __hash__(self):
return self.value.value + len(Face) * (self.suit.value - 1)
def __eq__(self, other):
if not isinstance(other, Card):
return False
return self.suit == other.suit and self.value == other.value
def __ne__(self, other):
if not isinstance(other, Card):
return True
return not self.__eq__(other)
def __str__(self):
return "%s of %s" % (self.value.name, self.suit.name)
def __lt__(self, other):
if self._deck.spades_high:
if other.suit == Suit.spades and self.suit != Suit.spades:
return True
if self.suit == Suit.spades and other.suit != Suit.spades:
return False
self_value = self.value.value
other_value = other.value.value
if self._deck.ace_high:
if self.value == Face.ace:
self_value = 14
if other.value == Face.ace:
other_value = 14
return self_value < other_value
def __gt__(self, other):
if self._deck.spades_high:
if other.suit == Suit.spades and self.suit != Suit.spades:
return False
if self.suit == Suit.spades and other.suit != Suit.spades:
return True
self_value = self.value.value
other_value = other.value.value
if self._deck.ace_high:
if self.value == Face.ace:
self_value = 14
if other.value == Face.ace:
other_value = 14
return self_value > other_value
def __le__(self, other):
return self.__eq__(other) or self.__lt__(other)
def __ge__(self, other):
return self.__eq__(other) or self.__gt__(other)