Begin implementing rules

This commit is contained in:
Mark Veidemanis 2022-03-11 17:18:09 +00:00
parent 4ad354354d
commit 857b26f4a3
Signed by: m
GPG Key ID: 5ACFCEED46C0904F
1 changed files with 310 additions and 0 deletions

310
blackjack.py Executable file
View File

@ -0,0 +1,310 @@
#!/usr/bin/env python3
import random
class NoMoreCards(Exception):
pass
class Game(object):
def __init__(self, deck, rules):
self.players = []
self.drawdeck = deck
self.playdeck = Deck()
self.rules = rules
# Which index player's turn is it?
self.player_index = 0
print("Created game.")
def next_turn(self):
current_player = self.players[self.current_player]
print(f"Current player is {current_player}")
if self.player_index == len(self.players):
print(f"Reached the end of players: {self.players}, {self.current_player}")
self.current_player = 0
else:
self.current_player += 1
print(f"Incrementing current_player: {self.players}, {self.current_player}")
def add_players(self, *players):
for player in players:
print(f"Adding player: {player}")
self.players.append(player)
def deal(self):
for player in self.players:
num_cards = self.rules.initial_cards
cards = list(self.drawdeck.draw_num(num_cards))
print("Cards", cards)
player.deck.put_cards(*cards)
if self.rules.flipcard:
first_card = self.drawdeck.draw()
print(f"First card is: {first_card}")
self.playdeck.put(first_card)
def play_card(self, player, card):
print(f"Player {player} attempting to play {card}")
last_card = self.playdeck.last_card
print(f"Last card {last_card}")
is_playable = self.rules.is_playable_on(last_card, card)
print("Card is playable", is_playable)
#current_card = self.d
class Player(object):
def __init__(self, name):
self.name = name
self.deck = Hand()
print(f"Created player {name}")
def __str__(self):
return self.name
def __repr__(self):
return self.__str__()
class SetOfCards(object):
def __init__(self, *cards):
self.cards = []
if cards:
self.cards = [*cards]
print(f"Created deck with cards: {self.cards}")
def draw(self):
card = self.cards.pop()
print(f"Drawing {card} from deck")
return card
def draw_num(self, num):
for i in range(0, num):
yield self.cards.pop()
def put(self, card):
print("Putting card on deck:", card)
self.cards.append(card)
def put_cards(self, *cards):
for card in cards:
self.put(card)
class Deck(SetOfCards):
def shuffle(self):
random.shuffle(self.cards)
print(f"Shuffled deck: {self.cards}")
@property
def last_card(self):
if self.cards:
return self.cards[-1]
else:
raise NoMoreCards
class Hand(SetOfCards):
pass
class Rules(object):
def __init__(self):
self.initial_cards = 2 # Number of cards to start with
self.flipcard = True # Initially flip a card
self.jacks_on_twos = False # Can we play Jacks on 2s?
self.jacks_on_eights = False # Can we play Jacks on 8s?
self.set_power_cards()
print("Created rules.")
def set_power_cards(self):
# Next player has to pick up two cards if they don't have a
# card of the same value
self.pick_up_two = Value(2)
# Next player has to skip a go if they don't have another
self.skip_a_turn = Value(8)
# How many cards to pick up
self.multiple_number = 6
pick_up_multiple_suits = [Suit("Spades"), Suit("Clubs")]
# Create a BlackJack filter
self.pick_up_multiple = Filter(pick_up_multiple_suits, Value("Jack"))
self.change_suit = Value("Ace")
self.specials_all = [self.pick_up_two,
self.skip_a_turn,
self.pick_up_multiple,
self.change_suit]
self.specials_power = self.specials_all[:-1]
print("Specials all", self.specials_all)
print("Power specials", self.specials_power)
def can_play_on_special(bottom_card, card):
# If the bottom card is a two
if bottom_card == self.pick_up_two:
# If the proposed card is not also the same
if card == self.pick_up_two:
return True
if self.jacks_on_twos:
if card == self.pick_up_mutiple:
return True
# We can only play 2s or Jacks if that is enabled
return False
# if the bottom card is a two
if bottom_card == self.skip_a_turn:
# if the proposed card is not also the same
if card == self.skip_a_turn:
return True
if self.jacks_on_eights:
# If the proposed card is a blackjack
if card == self.pick_up_multiple:
return True
# We can only play 8s or Jacks if that is enabled
return False
# If the bottom card is a Blackjack
if bottom_card == self.pick_up_multiple:
# If the card is the other Blackjack
if card == self.pick_up_multiple:
return True
return False
return False
def is_playable_on(bottom_card, card):
if bottom_card in self.rules.specials_all:
return self.can_play_on_special(bottom_card, card)
if card.suit == bottom_card.suit:
return True
if card.val == buttom_card.val:
return True
class Suit(object):
def __init__(self, suit):
self.suit = suit
def __str__(self):
return f"#{self.suit}"
def __repr__(self):
return self.__str__()
def __eq__(self, other):
return other.suit == self.suit
class Value(object):
def __init__(self, val):
self.val = val
self.numeric_value = self.get_numeric_value(val)
def get_numeric_value(self, val):
hash_map = {"Jack": 11, "Queen": 12, "King": 13, "Ace": 14}
if val in hash_map:
return hash_map[val]
else:
return val
def __gt__(self, other):
return self.numeric_value > other.numeric_value
def __lt__(self, other):
return self.numeric_value < other.numeric_value
def __eq__(self, other):
if isinstance(other, Value):
return self.numeric_value == other.numeric_value
def __str__(self):
return f".{str(self.val)}"
def __repr__(self):
return self.__str__()
@staticmethod
def multiple(*vals):
for val in vals:
yield Value(val)
class Filter(object):
def __init__(self, suits, val):
self.suits = suits
self.val = val
def __str__(self):
return f"|{self.val} of {self.suits}"
def __repr__(self):
return self.__str__()
def __eq__(self, other):
print("Filter EQ called")
print("other suit", other.suit)
print("our suits", self.suits)
print("other val", other.val)
print("our val", self.val)
if other.suit in self.suits and other.val == self.val:
return True
else:
return False
class Card(object):
def __init__(self, suit=None, val=None):
self.suit = Suit(suit)
self.val = Value(val)
print(f"Created card with suit {suit} and value {self.val}")
def playable_on(self, card):
pass
def __str__(self):
return f"+({self.val} of {self.suit})"
def __repr__(self):
return self.__str__()
@staticmethod
def multiple_suit(val, suits):
for suit in suits:
card = Card()
card.suit = suit
card.val = val
yield card
mark = Player("Mark")
john = Player("John")
card1 = Card("Spades", "Ace")
card2 = Card("Diamonds", "Jack")
card4 = Card("Clubs", 3)
card5 = Card("Diamonds", 3)
card6 = Card("Hearts", 4)
deck = Deck(card1, card2, card4, card5, card6)
deck.shuffle()
rules = Rules()
game = Game(deck, rules)
game.add_players(mark, john)
game.deal()
print("Mark's cards:", mark.deck.cards)
print("John's cards:", john.deck.cards)
val1 = Value("Queen")
val2 = Value(2)
val3 = Value("Queen")
assert val1 > val2
assert val2 < val1
assert val3 == val1
filter_blackjack = Filter([Suit("Spades"), Suit("Clubs")], Value("Jack"))
blackjack1 = Card("Spades", "Jack")
blackjack2 = Card("Clubs", "Jack")
redjack1 = Card("Diamonds", "Jack")
redjack2 = Card("Hearts", "Jack")
assert blackjack1 == filter_blackjack
assert blackjack2 == filter_blackjack
assert redjack1 != filter_blackjack
assert redjack2 != filter_blackjack