#!/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