def check(m): p = game.get_player(m.author) verify_context = p is not None and m.channel == p.channel and p in game.turn command = m.content.split() verify_message = len(command) == 3 and command[0] == "$declare" if verify_context and verify_message: # make sure the number is equal to submission amount verify_numbers = True try: command[1] = int(command[1]) if command[1] != len(p.submit): verify_numbers = False except ValueError: verify_numbers = False # check that the card exists and is legal verify_cards = False global cards if command[2] in cards: if cards[command[2]]["type"] == "legal": verify_cards = True if verify_numbers and verify_cards: game.turn.remove(p) for i in range(command[1]): p.declare.append( Card(cards[command[2]]["name"], cards[command[2]]["value"], cards[command[2]]["penalty"], cards[command[2]]["type"])) return len(game.turn) == 0
def build_deck(con, deck_list, deck): for card in deck_list: card_record = db_utils.find_card(con, card[0]) if card_record is not None: card_data = { 'name': card_record[0], 'cmc': card_record[1], 'mana_cost': card_record[2], 'type_line': card_record[3] } my_card = Card(card_data) else: card_data = requests.get( 'https://api.scryfall.com/cards/named?fuzzy=' + card[0]).json() my_card = Card(card_data) db_utils.insert_card(con, Card(card_data)) for _ in range(int(card[1])): deck.add_card(my_card) sleep(0.1) # scryfall wants api requests limited to 10/sec
def test_two_trips(): sesh = Session(LOGGER, player_count=2) players = ['player1', 'player2'] for i, player in enumerate(players): sesh.players[i].name = player sesh.setup_game() sesh.players[0].hand[0] = Card('H', 12) sesh.players[0].hand[1] = Card('C', 12) sesh.players[1].hand[0] = Card('H', 2) sesh.players[1].hand[1] = Card('D', 13) sesh.community_cards[0] = Card('D', 12) sesh.community_cards[1] = Card('D', 8) sesh.community_cards[2] = Card('C', 8) sesh.community_cards[3] = Card('S', 8) sesh.community_cards[4] = Card('C', 11) res = sesh.get_best_hands() assert res[sesh.players[0]][0] == HandVal.FULL_HOUSE assert res[sesh.players[0]][1] == [12, 12, 12, 8, 8]
def test_royal_flush_2(): sesh = Session(LOGGER, player_count=2) players = ['player1', 'player2'] for i, player in enumerate(players): sesh.players[i].name = player sesh.setup_game() sesh.players[0].hand[0] = Card('D', 10) sesh.players[0].hand[1] = Card('D', 12) sesh.players[1].hand[0] = Card('C', 8) sesh.players[1].hand[1] = Card('C', 9) sesh.community_cards[0] = Card('D', 14) sesh.community_cards[1] = Card('D', 11) sesh.community_cards[2] = Card('C', 10) sesh.community_cards[3] = Card('D', 7) sesh.community_cards[4] = Card('D', 13) res = sesh.get_best_hands() assert res[sesh.players[0]][0] == HandVal.ROYAL_FLUSH assert res[sesh.players[0]][1] == [14, 13, 12, 11, 10] assert res[sesh.players[1]][0] == HandVal.STRAIGHT assert res[sesh.players[1]][1] == [11, 10, 9, 8, 7]
def test_straight_flush_2(): sesh = Session(LOGGER, player_count=2) players = ['player1', 'player2'] for i, player in enumerate(players): sesh.players[i].name = player sesh.setup_game() sesh.players[0].hand[0] = Card('D', 10) sesh.players[0].hand[1] = Card('D', 8) sesh.players[1].hand[0] = Card('C', 6) sesh.players[1].hand[1] = Card('C', 2) sesh.community_cards[0] = Card('C', 3) sesh.community_cards[1] = Card('C', 4) sesh.community_cards[2] = Card('C', 5) sesh.community_cards[3] = Card('D', 7) sesh.community_cards[4] = Card('C', 10) res = sesh.get_best_hands() assert res[sesh.players[0]][0] == HandVal.PAIR assert res[sesh.players[0]][1] == [10, 10, 8, 7, 5] assert res[sesh.players[1]][0] == HandVal.STRAIGHT_FLUSH assert res[sesh.players[1]][1] == [6, 5, 4, 3, 2]
def test_ace_high_straight(): sesh = Session(LOGGER, player_count=2) players = ['player1', 'player2'] for i, player in enumerate(players): sesh.players[i].name = player sesh.setup_game() sesh.players[0].hand[0] = Card('S', 14) sesh.players[0].hand[1] = Card('C', 2) sesh.players[1].hand[0] = Card('D', 10) sesh.players[1].hand[1] = Card('D', 8) sesh.community_cards[0] = Card('S', 13) sesh.community_cards[1] = Card('D', 12) sesh.community_cards[2] = Card('C', 11) sesh.community_cards[3] = Card('D', 7) sesh.community_cards[4] = Card('C', 10) res = sesh.get_best_hands() assert res[sesh.players[0]][0] == HandVal.STRAIGHT assert res[sesh.players[0]][1] == [14, 13, 12, 11, 10] assert res[sesh.players[1]][0] == HandVal.PAIR assert res[sesh.players[1]][1] == [10, 10, 13, 12, 11]
def test_three_pairs2(): sesh = Session(LOGGER, player_count=2) players = ['player1', 'player2'] for i, player in enumerate(players): sesh.players[i].name = player sesh.setup_game() sesh.players[0].hand[0] = Card('H', 12) sesh.players[0].hand[1] = Card('C', 13) sesh.players[1].hand[0] = Card('C', 10) sesh.players[1].hand[1] = Card('S', 10) sesh.community_cards[0] = Card('H', 8) sesh.community_cards[1] = Card('S', 13) sesh.community_cards[2] = Card('C', 8) sesh.community_cards[3] = Card('D', 7) sesh.community_cards[4] = Card('C', 11) res = sesh.get_best_hands() assert res[sesh.players[0]][0] == HandVal.TWO_PAIR assert res[sesh.players[0]][1] == [13, 13, 8, 8, 12] assert res[sesh.players[1]][0] == HandVal.TWO_PAIR assert res[sesh.players[1]][1] == [10, 10, 8, 8, 13]
def test_pockets(): sesh = Session(LOGGER, player_count=2) players = ['player1', 'player2'] for i, player in enumerate(players): sesh.players[i].name = player sesh.setup_game() sesh.players[0].hand[0] = Card('H', 12) sesh.players[0].hand[1] = Card('S', 12) sesh.players[1].hand[0] = Card('C', 10) sesh.players[1].hand[1] = Card('S', 10) sesh.community_cards[0] = Card('H', 9) sesh.community_cards[1] = Card('S', 4) sesh.community_cards[2] = Card('C', 8) sesh.community_cards[3] = Card('D', 7) sesh.community_cards[4] = Card('C', 13) res = sesh.get_best_hands() assert res[sesh.players[0]][0] == HandVal.PAIR assert res[sesh.players[0]][1] == [12, 12, 13, 9, 8] assert res[sesh.players[1]][0] == HandVal.PAIR assert res[sesh.players[1]][1] == [10, 10, 13, 9, 8]
def test_flush_1(): sesh = Session(LOGGER, player_count=2) players = ['player1', 'player2'] for i, player in enumerate(players): sesh.players[i].name = player sesh.setup_game() sesh.players[0].hand[0] = Card('H', 12) sesh.players[0].hand[1] = Card('S', 13) sesh.players[1].hand[0] = Card('D', 3) sesh.players[1].hand[1] = Card('D', 2) sesh.community_cards[0] = Card('H', 10) sesh.community_cards[1] = Card('C', 10) sesh.community_cards[2] = Card('D', 5) sesh.community_cards[3] = Card('D', 7) sesh.community_cards[4] = Card('D', 12) res = sesh.get_best_hands() assert res[sesh.players[0]][0] == HandVal.TWO_PAIR assert res[sesh.players[0]][1] == [12, 12, 10, 10, 13] assert res[sesh.players[1]][0] == HandVal.FLUSH assert res[sesh.players[1]][1] == [12, 7, 5, 3, 2]
def _compute_streak_frequency(self, handcounts, kickers, sorted_cards) -> None: if sorted_cards[-1].value == 14: #count ace as lowest and highest sorted_cards.insert(0, Card(sorted_cards[-1].suit, 1)) self.log.debug(f'sorted cards post ace insert: {sorted_cards}') prev_num = -1 suit_streak = 0 streak = 1 prev_suit = [sorted_cards[0].suit] for card in sorted_cards: self.log.debug(f'\ncard: {card}') if prev_num + 1 == card.value: streak += 1 for suit in prev_suit: if suit == card.suit: suit_streak = suit_streak + 1 prev_suit = [suit] break suit_streak = 1 elif prev_num == card.value: streak = streak suit_streak = suit_streak prev_suit.append(card.suit) else: streak = 1 suit_streak = 1 prev_suit = [card.suit] self.log.debug(f'value streak: {streak} ') self.log.debug(f'suit streak: {suit_streak}') self.log.debug(f'prev suit: {prev_suit}') prev_num = card.value if streak >= 5 and suit_streak >= 5: if card.value == 14: self.log.info(f'{card.suit} royal flush!') kickers[HandVal.ROYAL_FLUSH] = [14, 13, 12, 11, 10] handcounts[HandVal.ROYAL_FLUSH] = 1 else: self.log.info(f'{card}-high straight flush!') range_ = reversed(range(card.value - 4, card.value + 1)) kickers[HandVal.STRAIGHT_FLUSH] = [i for i in range_] handcounts[HandVal.STRAIGHT_FLUSH] = 1 elif streak >= 5: self.log.debug(f'{card}-high straight!') handcounts[HandVal.STRAIGHT] = 1 range_ = reversed(range(card.value - 4, card.value + 1)) kickers[HandVal.STRAIGHT] = [i for i in range_]
def test_high_card(): sesh = Session(LOGGER, player_count=2) players = ['player1', 'player2'] for i, player in enumerate(players): sesh.players[i].name = player sesh.setup_game() sesh.players[0].hand[0] = Card('H', 12) sesh.players[0].hand[1] = Card('S', 14) sesh.players[1].hand[0] = Card('C', 2) sesh.players[1].hand[1] = Card('D', 6) sesh.community_cards[0] = Card('D', 10) sesh.community_cards[1] = Card('S', 9) sesh.community_cards[2] = Card('C', 5) sesh.community_cards[3] = Card('D', 3) sesh.community_cards[4] = Card('C', 13) res = sesh.get_best_hands() assert res[sesh.players[0]][0] == HandVal.HIGH_CARD assert res[sesh.players[0]][1] == [14, 13, 12, 10, 9] assert res[sesh.players[1]][0] == HandVal.HIGH_CARD assert res[sesh.players[1]][1] == [13, 10, 9, 6, 5]
def test_ace_low_straight(): sesh = Session(LOGGER, player_count=2) players = ['player1', 'player2'] for i, player in enumerate(players): sesh.players[i].name = player sesh.setup_game() sesh.players[0].hand[0] = Card('S', 14) sesh.players[0].hand[1] = Card('C', 2) sesh.players[1].hand[0] = Card('D', 10) sesh.players[1].hand[1] = Card('D', 8) sesh.community_cards[0] = Card('S', 3) sesh.community_cards[1] = Card('D', 4) sesh.community_cards[2] = Card('C', 5) sesh.community_cards[3] = Card('D', 9) sesh.community_cards[4] = Card('C', 10) res = sesh.get_best_hands() assert res[sesh.players[0]][0] == HandVal.STRAIGHT for i in reversed(range(2, 6)): assert res[sesh.players[0]][1][5 - i] == i assert res[sesh.players[0]][1][-1] == 1 #ace assert res[sesh.players[1]][0] == HandVal.PAIR assert res[sesh.players[1]][1] == [10, 10, 9, 8, 5]
def find_deck_cards(con, deck): sql = """ SELECT ac.name, ac.cmc, ac.mc, ac.type, dc.count FROM deck_cards dc JOIN all_cards ac ON dc.card_name = ac.name WHERE dc.deck_id = ? """ cur = con.cursor() cur.execute(sql, [deck.id]) res = cur.fetchall() for r in res: card_data = { 'name': r[0], 'cmc': r[1], 'mana_cost': r[2], 'type_line': r[3] } my_card = Card(card_data) for _ in range(r[4]): deck.add_card(my_card)
def main(): print("Cards - Tester") print() #test sorting of the cards testcardsList = [ Card("Spades", "Ace"), Card("Hearts", "Queen"), Card("Clubs", "10"), Card("Diamonds", "3"), Card("Hearts", "Jack"), Card("Spades", "7") ] testcardsList.sort() print("TEST CARDS LIST AFTER SORTING.") for c in testcardsList: print(c) print() # test deck print("DECK") deck = Deck() print("Deck created.") deck.shuffle() print("Deck shuffled.") print("Deck count:", len(deck)) print() # test hand hand = Hand() for i in range(10): hand.addCard(deck.dealCard()) print("SORTED HAND") for c in sorted(hand): print(c) print() print("Hand points:", hand.points) print("Hand count:", len(hand)) print("Deck count:", len(deck))
class Session: """ The Session class of a poker game. The Session is responsible for encapsulating the logic and rules of the game. === Attributes === log: logger object used to record various session debugging information. community_cards: list holding the comunity cards of a given game. community cards are 5 cards that every player can use in conjunction with their hole cards (hand) to make the best possible combination. deck: standard deck of 52 cards stored in a deque. players: list of Player objects taking part in the session. === Representation Invariants === len(deck) == 52 len(players) > 1 """ ALL_CARDS = [] for i in range(1, 14): for suit in SUITS: ALL_CARDS.append(Card(suit, i)) POSSIBLE_TABLES = list(itertools.combinations(ALL_CARDS, 5)) def __init__(self, log, player_count=2): self.log = log self.log.info('New session started.') self.community_cards = [] self.deck = deque(self.ALL_CARDS) self.players = [] for i in range(player_count): self.players.append(Player(position=i)) def compute_game_outcome(self): """returns the player who won the current game.""" pass def log_state(self) -> None: """Logs the current game state (player hands and community cards).""" for player in self.players: self.log.info(f"{player.name}'s hand: {player.hand}") self.log.info(f"Community Cards: {self.community_cards}") def setup_game(self): """starts a new game by resetting appropriate Session attributes.""" self.community_cards = [] self.log.info('shuffling...') self.deck = deque(self.ALL_CARDS) shuffle(self.deck) for player in self.players: player.hand = [] player.hand.append(self.deck.pop()) player.hand.append(self.deck.pop()) for _ in range(5): self.community_cards.append(self.deck.pop()) def _compute_flush_frequency(self, handcounts, suitcounts, kickers, sorted_cards) -> None: for suit, freq in suitcounts.items(): if freq >= 5: handcounts[HandVal.FLUSH] += 1 self.log.info(f'flush!') inc = 0 self.log.debug(sorted_cards[::-1]) for card_ in sorted_cards[::-1]: if card_.suit == suit: kickers[HandVal.FLUSH][inc] = card_.value inc += 1 if inc == 5: break def _compute_pair_frequency(self, handcounts, suitcounts, kickers, sorted_cards) -> None: """Computes the frequencies of pairs, trips, quads and full houses. Categorizes kickers based on hand-appropriate logic. """ # check for pair, trips and quads counted = [] for base_card in sorted_cards: suitcounts[base_card.suit] += 1 val_count = 1 #create copy of list with base card removed without_base = [x for x in sorted_cards if x != base_card] for card in without_base: if base_card.value == card.value and base_card not in counted: val_count += 1 counted.append(card) if val_count == 2: start = handcounts[HandVal.PAIR] * 2 end = start + 2 kickers[HandVal.PAIR][start:end] = [base_card.value] * 2 handcounts[HandVal.PAIR] += 1 self.log.debug(f'pair kickers: {kickers[HandVal.PAIR]}') self.log.info(f"pair!") elif val_count == 3: start = handcounts[HandVal.TRIPS] * 3 end = start + 3 handcounts[HandVal.TRIPS] += 1 kickers[HandVal.TRIPS][start:end] = [base_card.value] * 3 self.log.info(f'trips!') elif val_count == 4: kickers[HandVal.QUADS][0:4] = base_card.value handcounts[HandVal.QUADS] += 1 self.log.info(f'quads!') if handcounts[HandVal.PAIR] > 1: handcounts[HandVal.TWO_PAIR] += 1 kickers[HandVal.TWO_PAIR] = sorted(kickers[HandVal.PAIR])[::-1] if handcounts[HandVal.PAIR] > 2: self.log.debug(f'more than two pairs.') self.log.debug( f'kickers pre-insertion: {kickers[HandVal.TWO_PAIR]}') kickers[HandVal.TWO_PAIR] = kickers[HandVal.TWO_PAIR][:4] + [0] self.log.debug( f'kickers post-insertion: {kickers[HandVal.TWO_PAIR]}') self.log.info(f'two pair!') self.log.debug(f'two pair kickers: {kickers[HandVal.TWO_PAIR]}') def _compute_full_house_frequency(self, handcounts, kickers): if handcounts[HandVal.PAIR] >= 1 and handcounts[HandVal.TRIPS] >= 1: handcounts[HandVal.FULL_HOUSE] += 1 kickers[HandVal.FULL_HOUSE][:3] = kickers[HandVal.TRIPS][:3] kickers[HandVal.FULL_HOUSE][3:] = kickers[HandVal.PAIR][:2] self.log.info(f'full house!') if handcounts[HandVal.TRIPS] >= 2: handcounts[HandVal.FULL_HOUSE] += 1 kickers[HandVal.FULL_HOUSE] = sorted( kickers[HandVal.TRIPS])[:-6:-1] self.log.info(f'two trips and full house!') def _compute_streak_frequency(self, handcounts, kickers, sorted_cards) -> None: if sorted_cards[-1].value == 14: #count ace as lowest and highest sorted_cards.insert(0, Card(sorted_cards[-1].suit, 1)) self.log.debug(f'sorted cards post ace insert: {sorted_cards}') prev_num = -1 suit_streak = 0 streak = 1 prev_suit = [sorted_cards[0].suit] for card in sorted_cards: self.log.debug(f'\ncard: {card}') if prev_num + 1 == card.value: streak += 1 for suit in prev_suit: if suit == card.suit: suit_streak = suit_streak + 1 prev_suit = [suit] break suit_streak = 1 elif prev_num == card.value: streak = streak suit_streak = suit_streak prev_suit.append(card.suit) else: streak = 1 suit_streak = 1 prev_suit = [card.suit] self.log.debug(f'value streak: {streak} ') self.log.debug(f'suit streak: {suit_streak}') self.log.debug(f'prev suit: {prev_suit}') prev_num = card.value if streak >= 5 and suit_streak >= 5: if card.value == 14: self.log.info(f'{card.suit} royal flush!') kickers[HandVal.ROYAL_FLUSH] = [14, 13, 12, 11, 10] handcounts[HandVal.ROYAL_FLUSH] = 1 else: self.log.info(f'{card}-high straight flush!') range_ = reversed(range(card.value - 4, card.value + 1)) kickers[HandVal.STRAIGHT_FLUSH] = [i for i in range_] handcounts[HandVal.STRAIGHT_FLUSH] = 1 elif streak >= 5: self.log.debug(f'{card}-high straight!') handcounts[HandVal.STRAIGHT] = 1 range_ = reversed(range(card.value - 4, card.value + 1)) kickers[HandVal.STRAIGHT] = [i for i in range_] def _compute_result(self, player) -> Tuple[HandVal, List[int]]: empties = [[0 for _ in range(5)] for k in enumerate(HandVal)] kickers = dict(zip(HandVal, empties)) cards = player.hand + self.community_cards handcounts = dict(zip(HandVal, [0 for i in enumerate(HandVal)])) suitcounts = dict(zip(SUITS, [0 for i in enumerate(SUITS)])) sorted_cards = sorted(cards, key=lambda card: card.value) self.log.debug(f'sorted cards: {sorted_cards}') self._compute_pair_frequency(handcounts, suitcounts, kickers, sorted_cards) self._compute_flush_frequency(handcounts, suitcounts, kickers, sorted_cards) self._compute_full_house_frequency(handcounts, kickers) self._compute_streak_frequency(handcounts, kickers, sorted_cards) handcounts[HandVal.HIGH_CARD] = 1 for hand, freq in handcounts.items(): self.log.debug(f"{hand}:{freq}") if freq > 0: #fill kicker with highcards as required num_needed = kickers[hand].count(0) if num_needed > 0: high_cards = copy(sorted_cards[::-1]) high_cards = [ card.value for card in high_cards if card.value not in kickers[hand] ] kickers[hand][-num_needed:] = high_cards[:num_needed] return (hand, kickers[hand]) return None #never happens, makes linter happy def get_best_hands(self): """returns the best hand each player holds. the kickers sorted from most to least relevant. """ results = {} for player in self.players: results[player] = self._compute_result(player) return results
def main(): print("Blackjack\n") print("Blackjack payout is 3:2\n") money = 0.0 start = datetime.now() print("Start time: " + start.strftime("%I:%M:%S %p")) result = lc.setlocale(lc.LC_ALL, "") if result == "C": lc.setlocale(lc.LC_ALL, "en_US") while True: player = 0 dealer = 0 dealerHand = [] playerHand = [] card = Card() deck = Deck(card.getSuits(), card.getRanks()) deck.shuffle() d = deck.getDeck() number = random.randint(0, len(d)) # shows player money, lets them bet and ends if no money money = Money() money = money.getMoney() if money < 5: choice = input("Buy more chips? (y/n): ") if choice == "y": chips = float(input("Enter amount: ")) elif choice == "n": break localeMoney = Decimal(money) localeMoney = localeMoney.quantize(Decimal("1.00")) print("Money: " + lc.currency(localeMoney, grouping=True)) bet = float(input("Bet amount: ")) if bet < 5: print("Bet must be greater than $5") break elif bet > 1000: print("Bet must be less than $1000") break # shows dealer card and adds it to dealerHand print("DEALER'S SHOW CARD:") print(str(d[number][0]) + " of " + d[number][1]) dealer += cardCount(d[number][0]) dealerHand.append(d[number]) d.pop(number) print() # shows player's cards and adds them to playerHand print("YOUR CARDS:") for x in range(2): number = random.randint(0, len(d)) print(str(d[number][0]) + " of " + d[number][1]) player += cardCount(d[number][0]) playerHand.append(d[number]) d.pop(number) print() # determines if blackjack, if not, then player has a chance to hit or stand before dealer if dealer == 21: print("Dealer blackjack!") elif player == 21: print("Player blackjack") elif player < 21: choice = input("Hit or stand? (hit/stand): ") print() while player < 21 and choice == "hit": number = random.randint(0, len(d)) playerHand.append(d[number]) player += cardCount(d[number][0]) d.pop(number) print("YOUR CARDS:") for x in playerHand: print(str(x[0]) + " of " + x[1]) print() if player > 21: break choice = input("Hit or stand? (hit/stand): ") # Makes dealer draw cards until they have 17 points or until dealer has more points while dealer < 17: number = random.randint(0, len(d)) dealerHand.append(d[number]) dealer += cardCount(d[number][0]) while dealer < player: number = random.randint(0, len(d)) dealerHand.append(d[number]) dealer += cardCount(d[number][0]) # displays both hands and results print("DEALER'S CARDS:") for x in dealerHand: print(str(x[0]) + " of " + x[1]) print() print("YOUR POINTS:\t " + str(player)) print("DEALER'S POINTS: " + str(dealer)) print() with open("money.txt", "w", newline="") as file: end = datetime.now() if player > 21: print("Player busted! House always wins!") diff = money - bet ph = money money = round(money - bet, 2) localeMoney = Decimal(money) localeMoney = localeMoney.quantize(Decimal("1.00")) print("Money: " + lc.currency(localeMoney, grouping=True)) file.write(str(money)) elif dealer > 21: print("Dealer busted! Cash out, you're done at my tables") diff = money - bet ph = money money = round((bet * 1.5) + money, 2) localeMoney = Decimal(money) localeMoney = localeMoney.quantize(Decimal("1.00")) print("Money: " + lc.currency(localeMoney, grouping=True)) file.write(str(money)) elif player <= dealer: print("Player lost! Better luck next time, pal!") ph = money diff = money - bet money = round(money - bet, 2) localeMoney = Decimal(money) localeMoney = localeMoney.quantize(Decimal("1.00")) print("Money: " + lc.currency(localeMoney, grouping=True)) file.write(str(money)) print() choice = input("Play again? (y/n): ") if choice == "n": end = datetime.now() print("Stop time: " + end.strftime("%I:%M:%S %p")) hour = end.hour - start.hour minute = end.minute - start.minute second = end.second - start.second print("Elapsed time: " + str(hour) + ":" + str(minute) + ":" + str(second)) break