def render_action(self, player: Player, hand: BlackjackHand, action: BlackjackAction): if action == BlackjackAction.Hit: card = self.shoe.deal_card() hand.hit(card) print(f"\tHits {card}") self.hand_stack.append((player, hand)) elif action == BlackjackAction.Double: player.remove_money(hand.bet) card = self.shoe.deal_card() hand.double_up(card) print(f"\tDoubles {card}") elif action == BlackjackAction.Split: player.remove_money(hand.bet) hand1, hand2 = BlackjackHand.split_hand(hand) hand1.hit(self.shoe.deal_card()) hand2.hit(self.shoe.deal_card()) print(f"Split {hand1} {hand2}") self.hand_stack.append((player, hand1)) self.hand_stack.append((player, hand2)) elif action == BlackjackAction.Stay: pass elif action == BlackjackAction.Bust: pass elif action == BlackjackAction.Surrender: if not Ruleset.rules().get("late_surrender"): raise RuntimeError("Late Surrender is not Allowed!") player.add_money(hand.bet / 2) print(f"Surrendered! +{hand.bet / 2}") else: raise RuntimeError("Dunno how to handle this Action")
def payout(self, hands: List[Tuple[Player, BlackjackHand]], dealer_hand: BlackjackHand): dealer_total = dealer_hand.get_hand_total() print("\nResults:") print(f"Hand - {dealer_hand} - {dealer_total}") summary_table = [] for player, hand in hands: hand_summary = [] player_total = hand.get_hand_total() if player == self.house: continue hand_summary += [ player.name, ",".join([str(x) for x in hand.cards]), hand.get_hand_total(), ] if dealer_hand.is_blackjack(): if hand.is_blackjack(): player.add_money(hand.bet) hand_summary.append("Bump") hand_summary.append(0) else: hand_summary.append("Got jacked!") hand_summary.append(-1 * hand.bet) else: if hand.is_busted(): hand_summary.append("Busted") hand_summary.append(-1 * hand.bet) elif hand.is_blackjack(): hand_summary.append("Blackjack") blackjack_win = (1.5 if Ruleset.rules().get( "blackjack_pays_3_to_2", False) else 1.2) * hand.bet hand_summary.append(blackjack_win) player.add_money(blackjack_win + hand.bet) elif dealer_total > 21: player.add_money(hand.bet * 2) # original and winnings hand_summary.append("Dealer Busted!") hand_summary.append(hand.bet) elif dealer_total > player_total: hand_summary.append("Dealer wins") hand_summary.append(-1 * hand.bet) elif player_total > dealer_total: player.add_money(hand.bet * 2) hand_summary.append("In the money") hand_summary.append(hand.bet) elif player_total == dealer_total: player.add_money(hand.bet) hand_summary.append("Bump") hand_summary.append(0) summary_table.append(hand_summary) print(tabulate(summary_table))
def get_action(self, game: GameDriver, hand: BlackjackHand): if hand.is_soft(): if hand.get_hand_total() >= 17 + ( 1 if Ruleset.rules().get("dealer_hits_on_soft_17") else 0): return BlackjackAction.Stay else: return BlackjackAction.Hit else: if hand.get_hand_total() >= 17: return BlackjackAction.Stay else: return BlackjackAction.Hit
def get_action(self, game: GameDriver, hand: BlackjackHand): if hand.is_splittable() and self.should_i_split( hand, game.dealer_card): return BlackjackAction.Split elif hand.is_soft(): highest_value = hand.get_hand_total() return self.soft_action_grid.loc[highest_value][ game.dealer_card.value] else: # Hard hand highest_value = hand.get_hand_total() return self.hard_action_grid.loc[highest_value][ game.dealer_card.value]
def play_hand(self, id=0): print(f"####### Playing Hand #{id} ######################") finished_hands = [] # Check shoe to make sure it has enough cards for player in self.players: try: bet = player.get_initial_bet(self) except NoMoneyBucko as ex: continue # I don't think dealing two cards in this order will change any odds hand = BlackjackHand( [self.shoe.deal_card(), self.shoe.deal_card()], bet) player.get_dealt(hand) self.hand_stack.append((player, hand)) dealer_hand = BlackjackHand( [self.shoe.deal_card(), self.shoe.deal_card()], 0) self.house.get_dealt(dealer_hand) self.dealer_card = self.house.get_showing_card() self.hand_stack.insert(0, (self.house, dealer_hand)) last_hand = None # While not everyone has stayed/busted while self.hand_stack and not dealer_hand.is_blackjack(): player, hand = self.hand_stack.pop() if last_hand != hand: print(f"{hand}:") last_hand = hand action = player.get_action(self, hand) self.render_action(player, hand, action) if action in [ BlackjackAction.Double, BlackjackAction.Stay, BlackjackAction.Bust, BlackjackAction.Surrender, ]: finished_hands.append((player, hand)) if dealer_hand.is_blackjack(): finished_hands = self.hand_stack self.hand_stack = [] # Calculate self.payout(finished_hands, dealer_hand) for player in self.players: player.record_money_value()
def split_hand(): return BlackjackHand( [ Card(CardValue.Eight, CardSuit.Spades), Card(CardValue.Eight, CardSuit.Clubs) ], 7, )
def hard_hand(): return BlackjackHand( [ Card(CardValue.King, CardSuit.Spades), Card(CardValue.Six, CardSuit.Spades) ], 13, )
def double_ace_hand(): cards = [] cards.append(Card(CardValue.Two, CardSuit.Spades)) cards.append(Card(CardValue.Ace, CardSuit.Spades)) cards.append(Card(CardValue.Four, CardSuit.Spades)) cards.append(Card(CardValue.Ace, CardSuit.Clubs)) hand = BlackjackHand(cards) return hand
def busted_hand(): return BlackjackHand( [ Card(CardValue.King, CardSuit.Spades), Card(CardValue.Eight, CardSuit.Clubs), Card(CardValue.Queen, CardSuit.Clubs), ], 7, )
def get_action(self, game: GameDriver, hand: BlackjackHand): if (Ruleset.rules().get("late_surrender") and hand.is_surrenderable() and self.df_surrender.loc[hand.get_hand_total(), game.dealer_card.value]): return BlackjackAction.Surrender elif hand.is_splittable() and self.df_split.loc[ hand.cards[0].value, game.dealer_card.value]: return BlackjackAction.Split elif hand.is_soft(): df = self.df_soft return df.loc[hand.get_hand_total(), game.dealer_card.value] else: df = self.df_hard return df.loc[hand.get_hand_total(), game.dealer_card.value]
def test_split_hand(cls, split_hand: BlackjackHand): hand1, hand2 = BlackjackHand.split_hand(split_hand) assert len(hand1.cards) == 1 assert hand1.cards[0] == split_hand.cards[0]
def soft_hand(): return BlackjackHand([ Card(CardValue.Ace, CardSuit.Spades), Card(CardValue.Six, CardSuit.Spades) ], 27)
def test_is_busted(cls, busted_hand: BlackjackHand): assert busted_hand.is_busted()
def test_is_splittable(cls, split_hand: BlackjackHand): assert split_hand.is_splittable()
def test_is_soft(cls, soft_hand: BlackjackHand): assert soft_hand.is_soft()
def test_valid_values_double_aces(cls, double_ace_hand: BlackjackHand): assert double_ace_hand.get_valid_values() == [8, 18]
def test_doubleaces(self, game: GameDriver, strat: BookStrategy): hand = BlackjackHand.from_string("A♠,A♦") action = strat.get_action(game, hand) assert action == BlackjackAction.Split
def test_possible_values(cls, soft_hand: BlackjackHand): assert soft_hand.get_possible_values() == [7, 17]
def test_surrender_hand(self, game: GameDriver, strat: IStrategy): hand = BlackjackHand.from_string("J♣,6♥") action = strat.get_action(game, hand) assert action == BlackjackAction.Surrender
def get_action(self, game: GameDriver, hand: BlackjackHand): if hand.is_busted(): return BlackjackAction.Bust return self.strategy.get_action(game, hand)
def test_possible_values_double_aces(cls, double_ace_hand: BlackjackHand): assert double_ace_hand.get_possible_values() == [8, 18, 28]
def test_under15_hard_hand2(self, game: GameDriver, strat: BookStrategy): hand = BlackjackHand.from_string("4♥,9♣") action = strat.get_action(game, hand) assert action == BlackjackAction.Hit