Example #1
0
def play_game():
    # Create and shuffle the Draw deck
    deck = Deck()
    deck.shuffle()

    # Create the play stacks
    stack1 = Stack("ascending")
    stack2 = Stack("ascending")
    stack3 = Stack("descending")
    stack4 = Stack("descending")
    stacks = [stack1, stack2, stack3, stack4]

    # Create the starting hands
    hand1 = Hand()
    hand1.draw(deck)

    # While there are still cards in the deck and hand...
    while deck.cards or hand1.cards:

        # Get a list of stack states with directions
        print("The stacks are:")
        states = []
        for stack in stacks:
            print(str(stack.state) + " " + stack.direction)

        # Determine how many cards MUST be played
        if deck.cards:
            requirement = 2
        else:
            requirement = 1

        plays = hand1.play(stacks, requirement)

        print(f"I was able to play {plays} cards")
        if plays < requirement:
            break
        hand1.draw(deck)

        print("I have the following cards in hand: " + ", ".join(hand1.cards_as_str()))

    # The game is over (didn't have enough plays)
    print("Done")

    cards_remaining = deck.size() + hand1.size()
    print(f"The Game ended with {cards_remaining} cards remaining.")
    if cards_remaining == 0:
        print("You have won The Game!!")
    elif cards_remaining < 11:
        print("You didn't win, but you did really good!")
    else:
        print("Sorry, you lost The Game. Better luck next time.")
    return cards_remaining
Example #2
0
def main():
    print("Running main.py")
    d = Deck()
    hole_cards = d.draw(2)
    # board = d.draw(5)
    board = [
        Card.from_int(1),
        Card.from_int(2),
        Card.from_int(15),
        Card.from_int(28),
        Card.from_int(5)
    ]
    print(utils.best_hand(hole_cards[0], hole_cards[1], board))
    print("Finished main.py")
def split_cards(card, deck):
    if deck.split is False:
        deck.cards.remove(card[0])
        deck.points = subtract_points(card_value(card[0]), deck.points)
        new_deck = Deck()
        new_deck.cards.append(card[0])
        new_deck.player = deck.player
        new_deck.points = card_value(card[0])
        new_deck.status = False
        print("This deck of {0} has split as following: {1}".format(
            deck.player, deck.cards))
        deck.split = True
        return new_deck
    return None
def hit(deck: Deck, name: Hand):
    '''
    Function draws a card from the deck and adds it to the hand.
    and the ace difference is taken into consideration.
    '''
    hit = deck.deal()
    name.draw_card(hit)
Example #5
0
 def __init__(self):
     self.cells = []
     for _ in xrange(4):
         self.cells.append(Cell())
     self.foundations = []
     for _ in xrange(4):
         self.foundations.append(Foundation())
     self.cascades = []
     for _ in xrange(8):
         self.cascades.append(Cascade())
     # TODO fill cascades with cards
     deck = Deck()
     deck.shuffle()
     for chunk in chunks(deck, 8):
         for cascade, card in izip(self.cascades, chunk):
             cascade.append(card)
Example #6
0
 def __init__(self):
     self.cells = []
     for _ in xrange(4):
         self.cells.append(Cell())
     self.foundations = []
     for _ in xrange(4):
         self.foundations.append(Foundation())
     self.cascades = []
     for _ in xrange(8):
         self.cascades.append(Cascade())
     # TODO fill cascades with cards
     deck = Deck()
     deck.shuffle()
     for chunk in chunks(deck, 8):
         for cascade, card in izip(self.cascades, chunk):
             cascade.append(card)
Example #7
0
def read_xml_file(fname):
    """
    Reads in .xml/.cod file to Deck object. Assumes Cockatrice export formatting

    Args:
        fname (str): filename containing deck information. Unlike
            other functions, cannot be Path object as minidom has
            difficulty reading in

    Returns:
        (Deck)
    """
    p = Path(fname)

    xmldoc = minidom.parse(fname)
    card_xml = xmldoc.getElementsByTagName("card")

    # build Deck object
    card_list = []
    errors = []
    for c in card_xml:
        card_name = c.attributes["name"].value
        card_count = int(c.attributes["number"].value)
        try:
            cclass = fetch_card_data(card_name, card_count)
            card_list.append(cclass)
        except KeyError:
            # if any cards don't exist, save in errors
            errors.append(card_name)

    return Deck(p.stem, card_list)
Example #8
0
    def __init__(self, natural=False, deck_num=1):
        self.action_space = spaces.Discrete(3)
        self.side_space = spaces.Discrete(2)
        self.observation_space = spaces.Tuple(
            (spaces.Discrete(32), spaces.Discrete(11), spaces.Discrete(2)))
        self.seed(0)

        # Flag to payout 1.5 on a "natural" blackjack win, like casino rules
        # Ref: http://www.bicyclecards.com/how-to-play/blackjack/
        self.natural = natural

        self.deck = Deck()

        self.deck.count = 0

        # Start the first game
        self.reset()
Example #9
0
def query_db(path, query, output="text"):
    """
    Query existing table, save Deck corresponding to new query

    if id included in query, populate Deck object

    Args:
        path (Path|str): path to database file
        query (str): SQL query to be run
        output (str): how to output query results - 'text' or 'images'

    Returns:
        (Deck): corresponding to query results
    """
    p = Path(path)
    db = sqlite3.connect(p)
    query_df = pd.read_sql(query, db)

    # get Deck object corresponding to query if id in query
    cards = []
    cursor = db.cursor()
    if "id" in query_df.columns:
        all_ids = tuple(query_df["id"])
        cursor.execute(f"""SELECT name FROM {p.stem} WHERE id IN {all_ids}""")
        for row in cursor:
            cards.append(fetch_card_data(row[0], 1))

    deck = Deck(query, cards)

    # handle how to output results of query
    if output == "text":
        query_df.to_csv(query + ".csv", sep=" ", index=False)
    elif output == "images":
        deck.store_images(query)
    else:
        pass

    return deck
Example #10
0
    def __init__(self,
                 players,
                 small_blind=1,
                 big_blind=2,
                 dealer_seat=0,
                 debug_level=0):
        self.debug_level = debug_level
        self.players = players
        self.deck = Deck()
        self.small_blind = small_blind
        self.big_blind = big_blind
        self.pot = 0
        self.curr_raise = 0
        self.num_players_in_hand = len(self.players)
        self.num_active_players_in_hand = self.num_players_in_hand
        self.communal_cards = []

        self.initiate_round(dealer_seat)

        utils.out('---------------------------------------', self.debug_level)
        utils.out(
            '%s(%d) is dealer.' %
            (self.players[dealer_seat].name, self.players[dealer_seat].chips),
            self.debug_level)
Example #11
0
def set_up_game():
    players = []
    amount_of_players = ask_for_amount_of_players()

    for _ in range(0, amount_of_players):
        player_name = ask_player_for_name()
        player = Player(player_name)
        players.append(player)

    global deck
    if amount_of_players > 3:
        amount_of_decks = int(amount_of_players / 3)  # max 3 players per deck
        deck = Deck(amount_of_decks)

    bank = Player('The bank')
    start_round(players, bank)
Example #12
0
	def __init__(self, players, small_blind=1, big_blind=2, dealer_seat=0, debug_level=0):
		self.debug_level = debug_level	
		self.players = players
		self.deck = Deck()
		self.small_blind = small_blind
		self.big_blind = big_blind
		self.pot = 0
		self.curr_raise = 0
		self.num_players_in_hand = len(self.players)
		self.num_active_players_in_hand = self.num_players_in_hand
		self.communal_cards = []
		
		self.initiate_round(dealer_seat)
		
		utils.out('---------------------------------------', self.debug_level)
		utils.out('%s(%d) is dealer.' % (self.players[dealer_seat].name, self.players[dealer_seat].chips),
			self.debug_level)
Example #13
0
def db_to_deck(path):
    """
    Converts sqlite table to Deck object if none previously exists

    used when loading new deck from table

    Args:
        path (Path): path to database file
    """
    p = Path(path)
    db = sqlite3.connect(p)
    query_df = pd.read_sql(f"""SELECT name, count FROM {p.stem}""", db)
    names, counts = list(query_df["name"]), list(query_df["count"])

    cards = []
    for name, count in zip(names, counts):
        c = fetch_card_data(name, count)
        cards.append(c)

    return Deck(p.stem, cards)
Example #14
0
def read_text_file(fname):
    """
    Reads in common text file formats (.txt, .csv, .tsv), to Deck

    Parsing assumes formatting from tappedout export function

    Args:
        fname (str): filename containing deck information

    Returns:
        (Deck)
    """

    p = Path(fname)

    # read fname into df, handle formatting. txt requires preprocessing
    if (p.suffix == ".txt") or (p.suffix == ".dek"):
        df = pad_txt_file(p)
    # read csv/tsv into df, no preprocessing required
    elif p.suffix == ".csv":
        df = pd.read_csv(fname)
    elif p.suffix == ".tsv":
        df = pd.read_csv(fname, sep="\t")
    else:
        sys.exit("Invalid file format")

    df = df.dropna(subset=["Qty", "Name"])
    # get name & qty from df
    card_names = df["Name"].values.tolist()
    qty = df["Qty"].values.tolist()

    # build deck object
    card_list = []
    errors = []  # currently not doing anything with this, may use in future
    for c, q in zip(card_names, qty):
        try:
            card_list.append(fetch_card_data(c, q))
        except KeyError:
            # if any cards don't exist, save in errors
            errors.append(c)
    return Deck(p.stem, card_list)
Example #15
0
    async def deal(self, ctx):
        target_deck = 1
        deck_one = []
        deck_two = []
        deck = Deck()
        random.shuffle(deck.contents)
        for x in deck.contents:
            if target_deck == 1:
                deck_one.append(x)
                target_deck = 2
            else:
                deck_two.append(x)
                target_deck = 1
        else:

            deck_one_output = ""
            deck_one.sort(key=lambda y: (y.rank, y.suit))
            for i in deck_one:
                deck_one_output += f"{str(i)}\n"
            else:
                await ctx.send(f"Deck 1:\n{deck_one_output}")

            return [deck_one, deck_two]
Example #16
0
def main():
    '''Play game of 2 player blackjack on console.'''

    p1 = Player()
    p2 = Player()
    deck = Deck()
    p1_turn = True

    deck.shuffle()

    p1.hand.cards.append(deck.deal_card())
    p2.hand.cards.append(deck.deal_card())
    p1.hand.cards.append(deck.deal_card())
    p2.hand.cards.append(deck.deal_card())

    while not game_over(p1, p2):

        if p1_turn:
            if not p1.stay and not p1.blackjack and not p1.bust:
                print "\n\nPlayer One's Turn!"
                player_turn(p1, deck)
            p1_turn = False
        else:
            if not p2.stay and not p2.blackjack and not p2.bust:
                print "\n\nPlayer Two's Turn!"
                player_turn(p2, deck)
            p1_turn = True

    winner = get_winner(p1, p2)

    if winner is None:
        print "\nBoth players busted. Tie game!"
    elif winner == p1:
        print "\nPlayer One wins!"
    elif winner == p2:
        print "\nPlayer Two wins!"
    else:
        print "\nIt's a tie!"

    print "Game Over!"
Example #17
0
from classes import Player, Card, Deck

player_one = Player("One")
player_two = Player("Two")

new_deck = Deck()
new_deck.shuffle_deck()

for x in range(26):
    player_one.add_cards(new_deck.deal_one())
    player_two.add_cards(new_deck.deal_one())

game_on = True
at_war = False

round_num = 0

while game_on:
    round_num += 1

    if len(player_one.all_cards) == 0:
        print("Player One, out of cards! Player Two Wins!")
        game_on = False
        break

    if len(player_two.all_cards) == 0:
        print("Player Two, out of cards! Player One Wins!")
        game_on = False
        break

    player_one_cards = []
Example #18
0
#!/usr/bin/env python3
from __future__ import annotations
import random

from classes import Card, Player, Dealer, GameState, Deck

NUM_DECKS_IN_GAME = 6
STARTING_CASH = 200
MIN_BET = 5
MAX_SPLITS = 4

deck = Deck(NUM_DECKS_IN_GAME)
discard_pile = Deck(0)
player1 = Player(STARTING_CASH)
dealer = Dealer()
state = GameState.DEAL_CARDS
players = [player1]
Example #19
0
for later analysis
"""

from datetime import datetime
from classes import DAO, Player, Deck

MONGO_URI = "mongodb://localhost"  # MongoDB connection string
SAMPLES = 1000  # number of games to play
THRESHOLD = 15  # score under which Player will draw 1 card
NB_DECKS = 4  # number of decks to use. Decks are reshuffled when half the cards have been drawn
START_TIME = datetime.now()

mongo = DAO(MONGO_URI)
p_human = Player()
p_casino = Player()
c_deck = Deck(NB_DECKS)

for i in range(SAMPLES):
    p_human.draw_card(c_deck)
    p_casino.draw_card(c_deck)
    p_human.draw_card(c_deck)
    p_casino.draw_card(c_deck)

    if p_human.blackjack:
        if p_casino.blackjack:
            p_human.gain = 0  # Casino and Player both have a blackjack, it's a deuce
        else:
            p_human.gain = 2  # Player alone has a Blackjack, double win
    else:
        while p_human.score < THRESHOLD:  # Player will draw cards until reaching THRESHOLD score
            p_human.draw_card(c_deck)
Example #20
0
class Deal:
    def __init__(self,
                 players,
                 small_blind=1,
                 big_blind=2,
                 dealer_seat=0,
                 debug_level=0):
        self.debug_level = debug_level
        self.players = players
        self.deck = Deck()
        self.small_blind = small_blind
        self.big_blind = big_blind
        self.pot = 0
        self.curr_raise = 0
        self.num_players_in_hand = len(self.players)
        self.num_active_players_in_hand = self.num_players_in_hand
        self.communal_cards = []

        self.initiate_round(dealer_seat)

        utils.out('---------------------------------------', self.debug_level)
        utils.out(
            '%s(%d) is dealer.' %
            (self.players[dealer_seat].name, self.players[dealer_seat].chips),
            self.debug_level)

    def get_next_seat(self, seat, require_active=True, num_seats=None):
        result = seat
        if num_seats:
            for _ in range(num_seats):
                seat = self.get_next_seat(seat, require_active=require_active)
            return seat
        for i in range(len(self.players)):
            result = (result + 1) % len(self.players)
            if (self.players[result].in_hand and
                (not require_active or (not self.players[result].has_acted
                                        and not self.players[result].all_in))):
                return result
        return seat

    def set_all_other_players_active(self, seat):
        for i, player in enumerate(self.players):
            if seat != i and player.in_hand and not player.all_in and player.has_acted:
                player.has_acted = False
                self.num_active_players_in_hand += 1

    #Initiates round by setting player variables and collecting the small and big blinds.
    def initiate_round(self, dealer_seat):
        for player in self.players:
            player.draw_hand(self.deck)
            player.in_hand = True
            player.curr_bet = 0
            player.all_in = False
            player.has_acted = False
            player.sidepot = None

        self.pot = self.big_blind + self.small_blind
        self.bet = self.big_blind

        self.small_blind_seat = self.get_next_seat(dealer_seat)
        self.players[self.small_blind_seat].chips -= self.small_blind
        self.players[self.small_blind_seat].curr_bet = self.small_blind
        utils.out(
            '%s(%d) posts small blind of %d.' %
            (self.players[self.small_blind_seat].name,
             self.players[self.small_blind_seat].chips, self.small_blind),
            self.debug_level)

        big_blind_seat = self.get_next_seat(self.small_blind_seat)
        self.players[big_blind_seat].chips -= self.big_blind
        self.players[big_blind_seat].curr_bet = self.big_blind
        utils.out(
            '%s(%d) posts big blind of %d.' %
            (self.players[big_blind_seat].name,
             self.players[big_blind_seat].chips, self.big_blind),
            self.debug_level)

    def play_round(self):
        #Preflop
        for player in self.players:
            utils.out("%s is dealt %s" % (player.name, player.hand.read_out()),
                      self.debug_level)
        seat_to_act = self.get_next_seat(self.small_blind_seat, num_seats=2)
        if self.play_all_actions(seat_to_act):
            return
        self.clean_up_betting_round()

        #Flop
        self.communal_cards += self.deck.draw(num_cards=3)
        utils.out(
            "Flop: %s %s %s" % (self.communal_cards[0].read_out(),
                                self.communal_cards[1].read_out(),
                                self.communal_cards[2].read_out()),
            self.debug_level)
        if self.play_all_actions(self.small_blind_seat):
            return
        self.clean_up_betting_round()

        #Turn
        self.communal_cards += self.deck.draw()
        utils.out("Turn: %s" % self.communal_cards[3].read_out(),
                  self.debug_level)
        if self.play_all_actions(self.small_blind_seat):
            return
        self.clean_up_betting_round()

        #River
        self.communal_cards += self.deck.draw()
        utils.out("River: %s" % self.communal_cards[4].read_out(),
                  self.debug_level)
        if self.play_all_actions(self.small_blind_seat):
            return
        self.set_player_ranks()
        self.clean_up(players_by_rank=self.get_players_by_rank())

    def clean_up_betting_round(self):
        self.update_players_with_sidepots()
        for player in self.players:
            player.curr_bet = 0
            player.has_acted = False
        self.bet = 0
        self.curr_raise = 0
        self.num_active_players_in_hand = len([
            player for player in self.players
            if player.in_hand and not player.all_in
        ])

    def set_player_ranks(self):
        for player in self.players:
            if player.in_hand:
                player.rank = hand_rank.get_rank(player.hand.read_as_list() +
                                                 self.communal_cards)
                utils.out(
                    '%s(%s) has %s' % (player.name, player.hand.read_out(),
                                       player.rank._to_string()),
                    self.debug_level)

    def get_players_by_rank(self):
        return sorted([player for player in self.players if player.in_hand],
                      key=lambda x: x.rank,
                      cmp=hand_rank.Rank.compare_ranks)

    def get_winners_with_highest_rank(self, players_by_rank):
        winners = []
        winner = players_by_rank.pop()
        winners.append(winner)
        while len(players_by_rank) > 0:
            if players_by_rank[-1].rank.equals(winner.rank):
                winners.append(players_by_rank.pop())
            else:
                break
        return winners, players_by_rank

    def pay_winnings(self, winnings, winners):
        for i, winner in enumerate(winners):
            #Pay remainder to the first winner
            if i == 0:
                remainder = winnings % len(winners)
                winner.chips += remainder
                self.pot -= remainder
                utils.out(
                    '%s(%d) wins remainder of %d' %
                    (winner.name, winner.chips, remainder), self.debug_level)

            winner.chips += winnings / len(winners)
            utils.out(
                '%s(%d) wins %d chips with %s' %
                (winner.name, winner.chips, winnings, winner.hand.read_out()),
                self.debug_level)
            self.pot -= winnings / len(winners)
        return winners

    #While there is at least one winner with a sidepot, divide the minimum
    #sidepot among the winners and remove that winner from the list.
    def divide_sidepots_among_winners(self, winners):
        while any([winner.sidepot != None for winner in winners]):
            #Get the player with the smallest sidepot
            smallest_winner = min([w for w in winners if w.sidepot != None],
                                  key=lambda x: x.sidepot)

            #Distribute that player's sidepot among the winners
            winners = self.pay_winnings(smallest_winner.sidepot, winners)

            #Subtract that sidepot value from other players' sidepots
            for player in self.players:
                if player.in_hand and player.sidepot != None and player != smallest_winner:
                    player.sidepot -= smallest_winner.sidepot
                    if player.sidepot < 0:
                        player.sidepot = 0

            #Remove that player from the list of winners
            winners.remove(smallest_winner)

        return winners

    # If the hand went to showdown, show the winning cards and pay out the pot. If
    # not, the pot goes to the last remaining player in the hand.
    def clean_up(self, players_by_rank=None, winning_seat=None):
        #If the hand did not go to showdown, pay the entire pot to the remaining player.
        if winning_seat is not None:
            winner = self.players[winning_seat]
            winner.chips += self.pot
            utils.out(
                "%s(%d) wins the pot of %d" %
                (winner.name, winner.chips, self.pot), self.debug_level)

        #Otherwise, pay the pot to the winners in order of their hands, taking into account
        #sidepots and split pots.
        else:
            while self.pot > 0:
                #Get the set of winners with the highest rank
                winners, players_by_rank = self.get_winners_with_highest_rank(
                    players_by_rank)

                #Pay out the winners with the highest rank that have sidepots.
                winners = self.divide_sidepots_among_winners(winners)

                #If at least one winner did not have a sidepot, pay the remaining pot.
                if len(winners) > 0:
                    winners = self.pay_winnings(self.pot, winners)

    def go_to_showdown(self):
        num_cards = len(self.communal_cards)
        self.communal_cards += self.deck.draw(num_cards=5 - num_cards)
        if not num_cards:
            utils.out(
                "Flop: %s %s %s" % (self.communal_cards[0].read_out(),
                                    self.communal_cards[1].read_out(),
                                    self.communal_cards[2].read_out()),
                self.debug_level)
            utils.out("Turn: %s" % self.communal_cards[3].read_out(),
                      self.debug_level)
            utils.out("River: %s" % self.communal_cards[4].read_out(),
                      self.debug_level)
        elif num_cards == 3:
            utils.out("Turn: %s" % self.communal_cards[3].read_out(),
                      self.debug_level)
            utils.out("River: %s" % self.communal_cards[4].read_out(),
                      self.debug_level)
        elif num_cards == 4:
            utils.out("River: %s" % self.communal_cards[4].read_out(),
                      self.debug_level)

    #Loops through the players and plays their actions. If the hand ends during the loop, return
    #True, otherwise return False.
    def play_all_actions(self, seat_to_act):
        while self.num_active_players_in_hand > 0:
            action = self.players[seat_to_act].get_action(self)
            self.players[seat_to_act] = self.update_player_with_action(
                seat_to_act, action)
            #If, after this player's action, there is only one remaining player in the
            #hand, find that player and declare them the winner.
            if self.num_players_in_hand == 1:
                for i, player in enumerate(self.players):
                    if player.in_hand:
                        self.clean_up(winning_seat=i)
                return True
            if self.num_active_players_in_hand > 0:
                seat_to_act = self.get_next_seat(seat_to_act)

        #If at least all but one player in the hand is all in, run the remaining
        #communal cards and go to showdown.
        if len([player for player in self.players if player.all_in
                ]) >= self.num_players_in_hand - 1:
            self.update_players_with_sidepots()
            self.go_to_showdown()
            self.set_player_ranks()
            self.clean_up(players_by_rank=self.get_players_by_rank())
            return True
        return False

    def update_players_with_sidepots(self):
        for player in self.players:
            if player.in_hand:
                if player.all_in and not player.sidepot:
                    player.sidepot = self.get_sidepot(player)

    #Calculates the sidepot for a player as follows. For each other player in the hand,
    #add chips equal to that player's bet, or the given player's bet, whichever is
    #smaller. Then add the pot before the round started.
    def get_sidepot(self, player):
        bets_this_round = sum(player.curr_bet for player in self.players)
        pot_before_bet = self.pot - bets_this_round
        sidepot = pot_before_bet + player.curr_bet
        for other in self.players:
            #To do: players cannot have the same name
            if other.name != player.name:
                if other.curr_bet < player.curr_bet:
                    sidepot += other.curr_bet
                else:
                    sidepot += player.curr_bet
        utils.out('%s has a sidepot of %d' % (player.name, sidepot),
                  self.debug_level)
        return sidepot

    def update_player_with_check(self, player):
        utils.out('%s(%d) checks.' % (player.name, player.chips),
                  self.debug_level)

    def update_player_with_bet(self, player, bet_size):
        self.bet = bet_size
        player.curr_bet += self.bet
        player.chips -= self.bet
        self.pot += self.bet
        utils.out(
            "%s(%d) bets %d. Pot is %d" %
            (player.name, player.chips, self.bet, self.pot), self.debug_level)

    def update_player_with_call(self, player):
        #Note: call_amount is 0 in the case that the big blind calls preflop.
        amount_to_call = self.bet - player.curr_bet
        #Check if player is all-in
        if amount_to_call > player.chips:
            player.curr_bet += player.chips
            self.pot += player.chips
            utils.out(
                '%s(0) calls for %d and is all in. Pot is %d' %
                (player.name, player.chips, self.pot), self.debug_level)
            player.chips = 0
        else:
            player.curr_bet = self.bet
            player.chips -= amount_to_call
            self.pot += amount_to_call
            utils.out(
                "%s(%d) calls for %d. Pot is %d" %
                (player.name, player.chips, amount_to_call, self.pot),
                self.debug_level)

    def update_player_with_raise(self, player, raise_increase):
        amount_to_call = self.bet - player.curr_bet
        player.chips -= amount_to_call + raise_increase
        self.bet += raise_increase
        player.curr_bet = self.bet
        self.pot += amount_to_call + raise_increase
        self.curr_raise += raise_increase
        utils.out(
            "%s(%d) raises to %d. Pot is %d" %
            (player.name, player.chips, self.bet, self.pot), self.debug_level)

    def update_player_with_fold(self, player):
        player.in_hand = False
        self.num_players_in_hand -= 1
        utils.out('%s(%d) folds.' % (player.name, player.chips),
                  self.debug_level)

    #The action parameter stores as first index the name of the action, and as an optional
    #second index the size of the bet or raise.
    def update_player_with_action(self, seat, action):
        self.num_active_players_in_hand -= 1
        player = self.players[seat]
        player.has_acted = True
        if action[0] == 'check':
            self.update_player_with_check(player)
        if action[0] == 'bet':
            self.update_player_with_bet(player, action[1])
            self.set_all_other_players_active(seat)
        if action[0] == 'call':
            self.update_player_with_call(player)
        if action[0] == 'raise':
            self.update_player_with_raise(player, action[1])
            self.set_all_other_players_active(seat)
        if player.chips == 0:
            player.all_in = True
        if action[0] == 'fold':
            self.update_player_with_fold(player)
            #If the player who folded is the first to act, the next active player is now first to act.
            if seat == self.small_blind_seat:
                self.small_blind_seat = self.get_next_seat(
                    seat, require_active=False)
        return player
Example #21
0
from cheatsheet import masterCheatSheet, printQualities, printElem, printNums, printCourt
from classes import Card, Deck

q = ""
print("Hello! Welcome to Toasty Tarot. What would you like to do?\n")
while True:
    deck = Deck()
    print(
        "\t1. One card reading\n\t2. Three card reading\n\t3. Master cheat sheet\n\t4. What is tarot?\n\t5. [Exit]\n"
    )
    action = input("Please type in a number: ")
    print("\n.==========.==========.==========.==========.")

    if action == "1":
        q = input(
            "\nWhat would you like guidance on? (i.e. 'Where should I direct my energy today?'): "
        )
        deck.shuffle()
        print("\n================================================")
        print("|> " + q)
        print("================================================\n")
        c = deck.draw()
        c.show()

    elif action == "2":
        q = input(
            "\nWhat would you like guidance on? (i.e. 'Where should I direct my energy today?'): "
        )
        deck.shuffle()
        print("\n================================================")
        print("|> " + q)
Example #22
0
class Deal:
	def __init__(self, players, small_blind=1, big_blind=2, dealer_seat=0, debug_level=0):
		self.debug_level = debug_level	
		self.players = players
		self.deck = Deck()
		self.small_blind = small_blind
		self.big_blind = big_blind
		self.pot = 0
		self.curr_raise = 0
		self.num_players_in_hand = len(self.players)
		self.num_active_players_in_hand = self.num_players_in_hand
		self.communal_cards = []
		
		self.initiate_round(dealer_seat)
		
		utils.out('---------------------------------------', self.debug_level)
		utils.out('%s(%d) is dealer.' % (self.players[dealer_seat].name, self.players[dealer_seat].chips),
			self.debug_level)
	
	def get_next_seat(self, seat, require_active=True, num_seats=None):
		result = seat
		if num_seats:
			for _ in range(num_seats):
				seat = self.get_next_seat(seat, require_active=require_active)
			return seat	
		for i in range(len(self.players)):
			result = (result + 1) % len(self.players)
			if (self.players[result].in_hand and
			   (not require_active or 
				(not self.players[result].has_acted and not self.players[result].all_in))):
				return result
		return seat
		
	def set_all_other_players_active(self, seat):
		for i, player in enumerate(self.players):
			if seat != i and player.in_hand and not player.all_in and player.has_acted:
				player.has_acted = False
				self.num_active_players_in_hand += 1
	
	#Initiates round by setting player variables and collecting the small and big blinds.
	def initiate_round(self, dealer_seat):
		for player in self.players:
			player.draw_hand(self.deck)
			player.in_hand = True
			player.curr_bet = 0
			player.all_in = False
			player.has_acted = False
			player.sidepot = None
		
		self.pot = self.big_blind + self.small_blind
		self.bet = self.big_blind
		
		self.small_blind_seat = self.get_next_seat(dealer_seat)	
		self.players[self.small_blind_seat].chips -= self.small_blind
		self.players[self.small_blind_seat].curr_bet = self.small_blind
		utils.out('%s(%d) posts small blind of %d.' % (
			self.players[self.small_blind_seat].name,
			self.players[self.small_blind_seat].chips, self.small_blind),
			self.debug_level)

		big_blind_seat = self.get_next_seat(self.small_blind_seat)
		self.players[big_blind_seat].chips -= self.big_blind
		self.players[big_blind_seat].curr_bet = self.big_blind
		utils.out('%s(%d) posts big blind of %d.' % (
			self.players[big_blind_seat].name, self.players[big_blind_seat].chips, self.big_blind),
			self.debug_level)

	def play_round(self):
		#Preflop
		for player in self.players:
			utils.out("%s is dealt %s" % (player.name, player.hand.read_out()), self.debug_level)
                seat_to_act = self.get_next_seat(self.small_blind_seat, num_seats=2)
		if self.play_all_actions(seat_to_act):
			return                
		self.clean_up_betting_round()
		
		#Flop
		self.communal_cards += self.deck.draw(num_cards=3)
		utils.out("Flop: %s %s %s" % (self.communal_cards[0].read_out(), self.communal_cards[1].read_out(),
			self.communal_cards[2].read_out()), self.debug_level)
		if self.play_all_actions(self.small_blind_seat):
			return
		self.clean_up_betting_round()
		
		#Turn
		self.communal_cards += self.deck.draw()
		utils.out("Turn: %s" % self.communal_cards[3].read_out(), self.debug_level)
		if self.play_all_actions(self.small_blind_seat):
			return
		self.clean_up_betting_round()

		#River
		self.communal_cards += self.deck.draw()
		utils.out("River: %s" % self.communal_cards[4].read_out(), self.debug_level)
		if self.play_all_actions(self.small_blind_seat):
			return
		self.set_player_ranks()
		self.clean_up(players_by_rank = self.get_players_by_rank())
	
	def clean_up_betting_round(self):
		self.update_players_with_sidepots()
		for player in self.players:
			player.curr_bet = 0
			player.has_acted = False
		self.bet = 0
		self.curr_raise = 0
		self.num_active_players_in_hand = len(
			[player for player in self.players if player.in_hand and not player.all_in])

	def set_player_ranks(self):
		for player in self.players:
			if player.in_hand:
				player.rank = hand_rank.get_rank(
					player.hand.read_as_list() + self.communal_cards)
				utils.out('%s(%s) has %s' % (player.name,
					player.hand.read_out(), player.rank._to_string()), self.debug_level)
	
	def get_players_by_rank(self):
		return sorted([player for player in self.players if player.in_hand],
			      key = lambda x: x.rank,
			      cmp = hand_rank.Rank.compare_ranks)

	def get_winners_with_highest_rank(self, players_by_rank):
		winners = []
		winner = players_by_rank.pop()
		winners.append(winner)
		while len(players_by_rank) > 0:
			if players_by_rank[-1].rank.equals(winner.rank):
				winners.append(players_by_rank.pop())
			else:
				break
		return winners, players_by_rank

	def pay_winnings(self, winnings, winners):
		for i, winner in enumerate(winners):
			#Pay remainder to the first winner
			if i == 0:
				remainder = winnings % len(winners)
				winner.chips += remainder
				self.pot -= remainder
				utils.out('%s(%d) wins remainder of %d' % (winner.name, winner.chips,
					remainder), self.debug_level)

			winner.chips += winnings / len(winners)
			utils.out('%s(%d) wins %d chips with %s' % (winner.name, winner.chips,
				winnings, winner.hand.read_out()), self.debug_level)
			self.pot -= winnings / len(winners)
		return winners

	#While there is at least one winner with a sidepot, divide the minimum
	#sidepot among the winners and remove that winner from the list.
	def divide_sidepots_among_winners(self, winners):
		while any([winner.sidepot != None for winner in winners]):
			#Get the player with the smallest sidepot
			smallest_winner = min([w for w in winners if w.sidepot != None], key = lambda x: x.sidepot)
			
			#Distribute that player's sidepot among the winners
			winners = self.pay_winnings(smallest_winner.sidepot, winners)		
			
			#Subtract that sidepot value from other players' sidepots
			for player in self.players:
				if player.in_hand and player.sidepot != None and player != smallest_winner:
					player.sidepot -= smallest_winner.sidepot
					if player.sidepot < 0:
						player.sidepot = 0
			
			#Remove that player from the list of winners
			winners.remove(smallest_winner)
	
		return winners
				
	# If the hand went to showdown, show the winning cards and pay out the pot. If
	# not, the pot goes to the last remaining player in the hand.
	def clean_up(self, players_by_rank=None, winning_seat=None):
		#If the hand did not go to showdown, pay the entire pot to the remaining player.
		if winning_seat is not None:
			winner = self.players[winning_seat]
			winner.chips += self.pot
			utils.out("%s(%d) wins the pot of %d" % (
				winner.name, winner.chips, self.pot), self.debug_level)
		
		#Otherwise, pay the pot to the winners in order of their hands, taking into account
		#sidepots and split pots.
		else:
			while self.pot > 0:
				#Get the set of winners with the highest rank
				winners, players_by_rank = self.get_winners_with_highest_rank(players_by_rank)
				
				#Pay out the winners with the highest rank that have sidepots.
				winners = self.divide_sidepots_among_winners(winners)			
				
				#If at least one winner did not have a sidepot, pay the remaining pot.
				if len(winners) > 0:
					winners = self.pay_winnings(self.pot, winners)
					
	def go_to_showdown(self):
		num_cards = len(self.communal_cards)
		self.communal_cards += self.deck.draw(num_cards = 5 - num_cards)
		if not num_cards:
			utils.out("Flop: %s %s %s" % (self.communal_cards[0].read_out(), self.communal_cards[1].read_out(),
				self.communal_cards[2].read_out()), self.debug_level)
			utils.out("Turn: %s" % self.communal_cards[3].read_out(), self.debug_level)
			utils.out("River: %s" % self.communal_cards[4].read_out(), self.debug_level)
		elif num_cards == 3:
			utils.out("Turn: %s" % self.communal_cards[3].read_out(), self.debug_level)
			utils.out("River: %s" % self.communal_cards[4].read_out(), self.debug_level)
		elif num_cards == 4:	
			utils.out("River: %s" % self.communal_cards[4].read_out(), self.debug_level)
		
	#Loops through the players and plays their actions. If the hand ends during the loop, return
	#True, otherwise return False.
	def play_all_actions(self, seat_to_act):
		while self.num_active_players_in_hand > 0:
			action = self.players[seat_to_act].get_action(self)
                	self.players[seat_to_act] = self.update_player_with_action(seat_to_act, action)
			#If, after this player's action, there is only one remaining player in the
			#hand, find that player and declare them the winner.
			if self.num_players_in_hand == 1:
				for i, player in enumerate(self.players):
					if player.in_hand:
						self.clean_up(winning_seat = i)
				return True
			if self.num_active_players_in_hand > 0:
                		seat_to_act = self.get_next_seat(seat_to_act)

		#If at least all but one player in the hand is all in, run the remaining
		#communal cards and go to showdown.
		if len([player for player in self.players if player.all_in]) >= self.num_players_in_hand - 1:
			self.update_players_with_sidepots()
			self.go_to_showdown()
			self.set_player_ranks()
			self.clean_up(players_by_rank = self.get_players_by_rank())
			return True
		return False

	def update_players_with_sidepots(self):
		for player in self.players:
			if player.in_hand:
				if player.all_in and not player.sidepot:
					player.sidepot = self.get_sidepot(player)
	
	#Calculates the sidepot for a player as follows. For each other player in the hand,
	#add chips equal to that player's bet, or the given player's bet, whichever is
	#smaller. Then add the pot before the round started.
	def get_sidepot(self, player):
		bets_this_round = sum(player.curr_bet for player in self.players)
		pot_before_bet = self.pot - bets_this_round
		sidepot = pot_before_bet + player.curr_bet
		for other in self.players:
			#To do: players cannot have the same name
			if other.name != player.name:
				if other.curr_bet < player.curr_bet:
					sidepot += other.curr_bet
				else:
					sidepot += player.curr_bet
		utils.out('%s has a sidepot of %d' % (player.name, sidepot), self.debug_level)
		return sidepot

	
	def update_player_with_check(self, player):
		utils.out('%s(%d) checks.' % (player.name, player.chips), self.debug_level)

	def update_player_with_bet(self, player, bet_size):
		self.bet = bet_size
		player.curr_bet += self.bet
		player.chips -= self.bet
		self.pot += self.bet
		utils.out("%s(%d) bets %d. Pot is %d" % (
		player.name, player.chips, self.bet, self.pot), self.debug_level)

	def update_player_with_call(self, player):
		#Note: call_amount is 0 in the case that the big blind calls preflop.
		amount_to_call = self.bet - player.curr_bet
		#Check if player is all-in
		if amount_to_call > player.chips:
			player.curr_bet += player.chips
			self.pot += player.chips
			utils.out('%s(0) calls for %d and is all in. Pot is %d' % (
				player.name, player.chips, self.pot), self.debug_level)
			player.chips = 0
		else:
			player.curr_bet = self.bet
			player.chips -= amount_to_call
			self.pot += amount_to_call
			utils.out("%s(%d) calls for %d. Pot is %d" % (
				player.name, player.chips, amount_to_call, self.pot), self.debug_level)
			
	def update_player_with_raise(self, player, raise_increase):
		amount_to_call = self.bet - player.curr_bet
		player.chips -= amount_to_call + raise_increase
		self.bet += raise_increase
		player.curr_bet = self.bet
		self.pot += amount_to_call + raise_increase
		self.curr_raise += raise_increase
		utils.out("%s(%d) raises to %d. Pot is %d" % (
			player.name, player.chips, self.bet, self.pot), self.debug_level)

	def update_player_with_fold(self, player):
		player.in_hand = False
		self.num_players_in_hand -= 1
		utils.out('%s(%d) folds.' % (
			player.name, player.chips), self.debug_level)
	
	#The action parameter stores as first index the name of the action, and as an optional
	#second index the size of the bet or raise.
	def update_player_with_action(self, seat, action):
		self.num_active_players_in_hand -= 1
		player = self.players[seat]
		player.has_acted = True
		if action[0] == 'check':
			self.update_player_with_check(player)
		if action[0] == 'bet':
			self.update_player_with_bet(player, action[1])
			self.set_all_other_players_active(seat)	
		if action[0] == 'call':
			self.update_player_with_call(player)
		if action[0] == 'raise':
			self.update_player_with_raise(player, action[1])
			self.set_all_other_players_active(seat)
		if player.chips == 0:
			player.all_in = True
		if action[0] == 'fold':
			self.update_player_with_fold(player)
			#If the player who folded is the first to act, the next active player is now first to act.
			if seat == self.small_blind_seat:
				self.small_blind_seat = self.get_next_seat(seat, require_active = False)
		return player
Example #23
0
def create_deck():
    deck = Deck()
    deck.shuffle(deck)
    return deck
Example #24
0
    i = 1
    for each in range(0, players_num):
        player_list.append(Player(input(f"Enter name of Player{i}: "), i))
        i += 1

    new_round = True

    while new_round:

        for player in player_list:
            player.cards = []
            player.cards2 = []
        dealer.cards = []
        winners_list = []
        deck = Deck()
        deck.shuffle()

        # Dealing cards
        dealer.cards = deck.deal(2)

        print('')
        print('The dealer has 2 cards')
        print('You can only see one card of the dealer')
        print(f"One of the dealer's cards is {dealer.cards[0]}")
        print('')
        p_list = [dealer]
        paste_pics_normal(p_list, 1)
        starting_deal(player_list, deck)

        print('')
Example #25
0
 def test_draw_card(self):
     test_deck = Deck()
     test_deck.deal_card()
     self.assertEqual(len(test_deck.cards), 55)
# -*- coding: utf-8 -*-
"""
Created on Tue Dec 29 18:21:16 2020

@author: Samuel
"""
from classes import Card
from classes import Player
from classes import Deck

player1 = Player(input("Type your name, player1: "))
player2 = Player(input("Type your name, player2: "))

decker = Deck()
decker.shuffle()

for cd in range(26):
    player1.increase(decker.deal())
    player2.increase(decker.deal())

game_on = True
round = 0
while game_on:
    round += 1
    print("Round", round)

    if (len(player2.allcards) > len(player1.allcards)) and round >= 10000:
        print("Rounds up!", player1.name, "loses and", player2.name, "wins")
        game_on = False
        break
Example #27
0
def screen_clear():
    if name == 'nt':
        _ = system('cls')
    # for mac and linux(here, os.name is 'posix')
    else:
        _ = system('clear')


# print out some text
print('UNO Game\n')
sleep(2)
# now call function we defined above
screen_clear()

#Create deck
deck = Deck()
deck.create_cards()


#set number of players
def players_num():
    print("Enter number of players:")
    x = int(input())
    print("Number of players set to:", x)
    return x


#Create players
num = players_num()

Example #28
0
    chips.lose_bet()


def push(player, dealer):
    print("Tie!")


# GAMEPLAY

while True:
    print("""Let the game begin !
        You start with 100 chips
        Aces can be count as 1 o 11
        Dealer hits until he gets 17 or higher""")

    deck = Deck()
    deck.shuffle()

    player_hand = Hand()
    player_hand.add_card(deck.deal())
    player_hand.add_card(deck.deal())

    dealer_hand = Hand()
    dealer_hand.add_card(deck.deal())
    dealer_hand.add_card(deck.deal())

    player_chips = Chips()

    take_bet(player_chips)

    show_some(player_hand, dealer_hand)
def create_tables(num_of_tables, num):
    tables = []
    i = 0
    while i+1 <= num_of_tables:
        table = Table()
        bank = Bank()
        if i + 1 is num_of_tables:
            if num%3 == 0:
                for m in range(3):
                    print("Insert the name of player {}".format(i*3 + m + 1))
                    name = input()
                    player = Player()
                    player.name = name
                    deck = Deck()
                    player.decks.append(deck)
                    table.players.append(player)
                table.hand = shuffle_cards()
                table.id = i + 1
                bank.name = "Bank"
                bank.status = False
                table.bank = bank
                tables.append(table)
                if (i*3 + m + 1) == num:
                    break

            if (num-i*3)%2 == 0 and (num-i*3)//2 == 1:
                for m in range(2):
                    print("Insert the name of player {}".format(i*3 + m + 1))
                    name = input()
                    player = Player()
                    player.name = name
                    deck = Deck()
                    player.decks.append(deck)
                    table.players.append(player)
                table.hand = shuffle_cards()
                table.id = i + 1
                bank.name = "Bank"
                bank.status = False
                table.bank = bank
                tables.append(table)
                if i*3 + m + 1 == num:
                    break

            if ((num-3*i)//1) == 1:
                for m in range(1):
                    print("Insert the name of player {}".format(i*3 + m + 1))
                    name = input()
                    player = Player()
                    player.name = name
                    deck = Deck()
                    player.decks.append(deck)
                    table.players.append(player)
                table.hand = shuffle_cards()
                table.id = i + 1
                bank.name = "Bank"
                bank.status = False
                table.bank = bank
                tables.append(table)
                if (i*3 + m + 1) == num:
                    break
        else:
            for m in range(3):
                print("Insert the name of player {}".format(i*3 + m + 1))
                name = input()
                player = Player()
                player.name = name
                deck = Deck()
                player.decks.append(deck)
                table.players.append(player)
            table.hand = shuffle_cards()
            table.id = i + 1
            bank.name = "Bank"
            bank.status = False
            table.bank = bank
            tables.append(table)
            i = i + 1

    return tables
Example #30
0
 def test_deck_is_complete(self):
     test_deck = Deck()
     self.assertEqual(len(test_deck.cards), 56)
Example #31
0
from classes import Deck, Player, Game

eggbert = Player("Eggbert", Deck())
cpu = Player("Cpu", Deck())

game = Game(eggbert, cpu)

game.start()
Example #32
0
game = True
p_b = False
# Set up the Player's chips
p_chips = Chips('player', 100)
d_chips = Chips('delaer', 1000)
while game:
    # Print an opening statement
    print('Welcome to the Black jack game!')
    if p_chips.balance <= 0:
        print('you have no chips to play')
        break
    else:
        pass
    # Create & shuffle the deck, deal two cards to each player
    playing = True
    deck = Deck()
    deck.shuffle()
    dealer = Hand()
    player = Hand()
    player.add(deck.deal())
    player.add(deck.deal())
    dealer.add(deck.deal())
    dealer.add(deck.deal())

    # Prompt the Player for their bet
    bet = take_bet(p_chips)
    # Show cards (but keep one dealer card hidden)
    show_some(player, dealer)
    while playing:  # recall this variable from our hit_or_stand function
        # Prompt for Player to Hit or Stand
        playing = hit_or_stand(deck, player)
Example #33
0
suits = ('Hearts', 'Diamonds', 'Spades', 'Clubs')
ranks = ('Two', 'Three', 'Four', 'Five', 'Six', 'Seven', 'Eight', 'Nine',
         'Ten', 'Jack', 'Queen', 'King', 'Ace')
values = {
    'Two': 2,
    'Three': 3,
    'Four': 4,
    'Five': 5,
    'Six': 6,
    'Seven': 7,
    'Eight': 8,
    'Nine': 9,
    'Ten': 10,
    'Jack': 10,
    'Queen': 10,
    'King': 10,
    'Ace': 11
}
deck = Deck()
''' deal card to dealer and two cards for human'''
dealer = Hand()
player = Hand()
p_chips = Chips('player', 100)
d_chips = Chips('delaer', 100)
take_bet(p_chips)
'''
hit_or_stand(deck,player)

show_some(player,dealer)
'''
Example #34
0
class BlackjackEnv(gym.Env):
    def cmp(self, a, b):
        return float(a > b) - float(a < b)

    def draw_card_(self, card):
        c = self.deck.get_card_(card)
        return c

    def draw_card(self):
        card = self.deck.get_card()
        return card

    def draw_hand(self):
        h = Hand()
        h.cards = [self.deck.get_card(), self.deck.get_card()]
        h.usableAce = self.usable_ace(h)
        return h

    def usable_ace(self, hand):  # checks hands for a usable ace? **
        h_values = hand.getValues()
        for c in hand.cards:
            if c.name == "Ace":
                if sum(h_values) + 10 <= 21:
                    hand.usableAce = True
                    return True

        hand.usableAce = False
        return False

    def sum_hand(self, hand):  # Return current hand total **
        if self.usable_ace(hand):
            return sum(hand.getValues()) + 10
        return sum(hand.getValues())

    def is_bust(self, hand):  # Is this hand a bust?
        return self.sum_hand(hand) > 21

    def score(self, hand):  # What is the score of this hand (0 if bust) **
        score = 0

        if self.is_bust(hand):
            score = 0

        else:
            score = self.sum_hand(hand)

        return score

    def is_natural(self, hand):  # Is this hand a natural blackjack?
        return sorted(hand.getValues()) == [1, 10]

    """Simple blackjack environment
    Blackjack is a card game where the goal is to obtain cards that sum to as
    near as possible to 21 without going over.  They're playing against a fixed
    dealer.
    Face cards (Jack, Queen, King) have point value 10.
    Aces can either count as 11 or 1, and it's called 'usable' at 11.
    This game is placed with an infinite deck (or with replacement).
    The game starts with each (player and dealer) having one face up and one
    face down card.
    The player can request additional cards (hit=1) until they decide to stop
    (stick=0) or exceed 21 (bust).
    After the player sticks, the dealer reveals their facedown card, and draws
    until their sum is 17 or greater.  If the dealer goes bust the player wins.
    If neither player nor dealer busts, the outcome (win, lose, draw) is
    decided by whose sum is closer to 21.  The reward for winning is +1,
    drawing is 0, and losing is -1.
    The observation of a 3-tuple of: the players current sum,
    the dealer's one showing card (1-10 where 1 is ace),
    and whether or not the player holds a usable ace (0 or 1).
    This environment corresponds to the version of the blackjack problem
    described in Example 5.1 in Reinforcement Learning: An Introduction
    by Sutton and Barto.
    http://incompleteideas.net/book/the-book-2nd.html
    """

    def __init__(self, natural=False, deck_num=1):
        self.action_space = spaces.Discrete(3)
        self.side_space = spaces.Discrete(2)
        self.observation_space = spaces.Tuple(
            (spaces.Discrete(32), spaces.Discrete(11), spaces.Discrete(2)))
        self.seed(0)

        # Flag to payout 1.5 on a "natural" blackjack win, like casino rules
        # Ref: http://www.bicyclecards.com/how-to-play/blackjack/
        self.natural = natural

        self.deck = Deck()

        self.deck.count = 0

        # Start the first game
        self.reset()

    def seed(self, seed=None):
        self.np_random, seed = seeding.np_random(seed)
        return [seed]

    def step(self, action):
        assert self.action_space.contains(action)
        reward = 0

        if action == 1:  # hit: add a card to players hand and return
            self.playerHand.cards.append(self.draw_card())
            self.sum_hand(self.playerHand)
            if self.is_bust(self.playerHand):
                done = True
                reward = -1
            else:
                done = False
                reward = 0

        elif action == 0:  # stick: play out the dealers hand, and score
            done = True

            while sum(self.dealerHand.getValues()) < 17:
                self.dealerHand.cards.append(self.draw_card())
            reward = self.cmp(self.score(self.playerHand),
                              self.score(self.dealerHand))

            if self.is_natural(self.playerHand) and reward == 1:
                if self.is_natural(self.dealerHand):
                    # Push - original bet returned
                    reward = 0
                # natural blackjack pays out 3/2
                reward = 1.5

        elif action == 2:  # double: double bet and dealt a final card

            self.playerHand.cards.append(self.draw_card())
            self.sum_hand(self.playerHand)

            while sum(self.dealerHand.getValues()) < 17:
                self.dealerHand.cards.append(self.draw_card())

            if self.is_bust(self.playerHand):
                reward = -2
            else:
                reward = self.cmp(self.score(self.playerHand),
                                  self.score(self.dealerHand))
                reward *= 2
            done = True

        elif action == "3":  # split: split hand
            done = False
            # check for pair before calling
            self.player.append([self.player[0][1]])
            self.player.remove(self.player[0][1])

        return self._get_obs(), reward, done, 0

    def _get_obs(self):
        a = (self.sum_hand(self.playerHand), self.dealerHand.getValues()[0],
             self.usable_ace(self.playerHand))
        return a

    def get_hands(self):
        return self.playerHand, self.dealerHand

    def get_hand_cards(self):
        return self.playerHand.cards + [self.dealerHand.cards[0]]

    def reset(self):
        if (self.deck.last_hand or self.deck.deck_cards.count == 0):
            self.deck.gen_shoe()

        self.dealerHand = self.draw_hand()
        self.usable_ace(self.dealerHand)

        self.playerHand = self.draw_hand()
        self.usable_ace(self.playerHand)
        psum = self.sum_hand(self.playerHand)

        return self._get_obs()

    def reset_(self):
        self.deck.deck_cards + self.playerHand.cards
        self.deck.deck_cards + self.dealerHand.cards
        self.deck.shuffle_deck()
        self.playerHand = self.draw_hand()
        self.dealerHand = self.draw_hand()

        return self._get_obs()

    def deck_by_count(self, count):
        self.deck.gen_shoe()
        while True:
            c1_deck, c2_deck = self.deck.count_suits
            c1_deck //= self.deck.num_decks
            c2_deck //= self.deck.num_decks
            if tuple([
                    c1_deck, c2_deck
            ]) == count and self.deck.count < (52 * self.deck.num_decks // 2):
                return
            else:
                c1, c2 = zip(count)
                #c1_deck, c2_deck = zip(self.deck.count_suits)
                # check clubs & heart count and adjust
                c1 = c1[0]
                c2 = c2[0]
                if c1 > c1_deck:
                    temp = [
                        card for card in self.deck.deck_cards
                        if card.suit == self.deck.suits[0]
                    ]
                    if len(temp) == 0:
                        self.deck.gen_shoe()
                        continue
                    self.draw_card_(np.random.choice(temp))

                if c1 < c1_deck:
                    temp = [
                        card for card in self.deck.deck_cards
                        if card.suit == self.deck.suits[1]
                    ]
                    if len(temp) == 0:
                        self.deck.gen_shoe()
                        continue
                    self.draw_card_(np.random.choice(temp))

                if c2 > c2_deck:
                    temp = [
                        card for card in self.deck.deck_cards
                        if card.suit == self.deck.suits[2]
                    ]
                    if len(temp) == 0:
                        self.deck.gen_shoe()
                        continue
                    self.draw_card_(np.random.choice(temp))

                if c2 < c2_deck:
                    temp = [
                        card for card in self.deck.deck_cards
                        if card.suit == self.deck.suits[3]
                    ]
                    if len(temp) == 0:
                        self.deck.gen_shoe()
                        continue
                    self.draw_card_(np.random.choice(temp))