Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Binary file added project/UML.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
12 changes: 12 additions & 0 deletions project/example/example.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
from project.scr.persons import BlackjackPlayer
from project.scr.strategies import ConservativeStrategy
from project.scr.game import BlackjackGame

# Минимальный рабочий пример с одной стратегией
players = [
BlackjackPlayer(strategy=ConservativeStrategy(), initial_bankroll=100),
BlackjackPlayer(initial_bankroll=100), # Использует Conservative по умолчанию
]

game = BlackjackGame(players=players, num_decks=1) # 1 колода для простоты
game.play_full_round()
82 changes: 82 additions & 0 deletions project/example/example.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
=== BLACKJACK GAME SESSION ===

[ ROUND 1 INITIATED ]

• WAGERS PLACED:
- Player 1: $10
- Player 2: $10
- Player 3: $20 (high roller)
- Player 4: $10

• DEALER'S INITIAL MOVE:
Visible Card: ♦4
(Hidden card dealt)

• PLAYER ACTIONS:

Player #1:
Cards: ♣5 ♥9 (Total: 14)
Moves: Drew card, Drew card, Stand

Player #2:
Cards: ♠4 ♦6 ♥3 ♣8 (Total: 21)
Moves: Drew card, Drew card, Doubled bet, Drew card, Drew card

Player #3:
Cards: ♠10 ♣9 ♠3 (BUST)
Moves: Drew card, Drew card, Drew card

Player #4:
Cards: ♠8 ♣Q (Total: 18)
Moves: Drew card, Drew card, Stand

• DEALER'S TURN:
Revealed Hand: ♦4 ♣3 (Total: 7)
Final Hand: ♦4 ♣3 ♥6 ♠2 ♥5 (Total: 20)

• ROUND RESULTS:

Player #1: LOSS (14 vs 20)
Player #2: WIN (21)
Player #3: LOSS (Bust)
Player #4: LOSS (18 vs 20)

[ ROUND 1 CONCLUDED ]

[ ROUND 2 INITIATED ]

• WAGERS PLACED:
- Player 1: $10
- Player 2: $10
- Player 3: $20
- Player 4: Cannot bet (insufficient funds)

• DEALER'S INITIAL MOVE:
Visible Card: ♠6
(Hidden card dealt)

• PLAYER ACTIONS:

Player #1:
Cards: ♦Q ♥10 (Total: 20)
Moves: Drew card, Drew card, Stand

Player #2:
Cards: ♠A ♠5 ♥7 ♣4 (Total: 17)
Moves: Drew card, Drew card, Drew card, Drew card, Stand

Player #3:
Cards: ♠K ♦7 ♠3 (Total: 20)
Moves: Drew card, Drew card, Drew card, Stand

• DEALER'S TURN:
Revealed Hand: ♠6 ♥5 (Total: 11)
Final Hand: ♠6 ♥5 ♣6 (Total: 17)

• ROUND RESULTS:

Player #1: WIN (20 vs 17)
Player #2: PUSH (17 vs 17)
Player #3: WIN (20 vs 17)

[ ROUND 2 CONCLUDED ]
146 changes: 146 additions & 0 deletions project/scr/desk.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,146 @@
from typing import List, Dict
from project.scr.persons import BlackjackPlayer, BlackjackDealer
from project.scr.objects import PlayerHand, GameResult


class BlackjackTable:
"""
Manages the blackjack game flow, player actions, and dealer interactions.

Attributes:
players (List[BlackjackPlayer]): List of active players
dealer (BlackjackDealer): The game dealer
player_hands (Dict[BlackjackPlayer, List[PlayerHand]]): Active hands per player
"""

def __init__(self, players: List[BlackjackPlayer], num_decks: int = 6):
"""Initialize a new blackjack table"""
self.players = players
self.dealer = BlackjackDealer(num_decks)
self.player_hands: Dict[BlackjackPlayer, List[PlayerHand]] = {}
self._initialize_table()

def _initialize_table(self) -> None:
"""Prepare the table for a new round"""
self.dealer.new_round()
for player in self.players:
player.clear_hands()
new_hand = PlayerHand([])
player.add_hand(new_hand)
self.player_hands[player] = [new_hand]

def deal_card_to_hand(self, hand: PlayerHand, face_up: bool = True) -> None:
"""
Deal a card from the dealer's shoe to a specific hand

Args:
hand: The target hand to receive the card
face_up: Whether the card should be dealt face up
"""
card = self.dealer.deal_card(face_up)
hand.add_card(card)

def place_initial_bets(self) -> None:
"""Handle initial betting round for all players"""
for player in self.players:
if player.can_place_bet(player.strategy.min_bet):
bet_amount = player.strategy.min_bet
player.place_bet(bet_amount)
# Initialize bet for first hand
if self.player_hands[player]:
self.player_hands[player][0].wager = bet_amount
else:
# Mark player as out if can't place minimum bet
if self.player_hands[player]:
self.player_hands[player][0].status = GameResult.LOSE

def split_hand(self, player: BlackjackPlayer, hand_index: int = 0) -> None:
"""
Split a player's hand into two separate hands

Args:
player: The player requesting the split
hand_index: Index of the hand to split
"""
if hand_index >= len(self.player_hands[player]):
return

original_hand = self.player_hands[player][hand_index]

# Verify split is possible
if (
len(original_hand.cards) != 2
or original_hand.cards[0].rank != original_hand.cards[1].rank
):
return

# Create two new hands from the split
new_hand1, new_hand2 = original_hand.split_hand()

# Place additional bet
if player.can_place_bet(original_hand.wager):
player.place_bet(original_hand.wager)
else:
return

# Deal cards to new hands
self.deal_card_to_hand(new_hand1)
self.deal_card_to_hand(new_hand2)

# Replace original hand with split hands
self.player_hands[player].pop(hand_index)
self.player_hands[player].extend([new_hand1, new_hand2])
player.active_hands = self.player_hands[player]

def start_new_round(self) -> None:
"""Reset the table for a new round of play"""
self._initialize_table()

# Deal initial cards: 2 to each player, 1 to dealer + 1 face down
for _ in range(2):
for player in self.players:
for hand in self.player_hands[player]:
self.deal_card_to_hand(hand)

# Dealer gets one face up and one face down card
self.deal_card_to_hand(self.dealer.hand)
self.deal_card_to_hand(self.dealer.hand, face_up=False)

def player_action(
self, player: BlackjackPlayer, action: str, hand_index: int = 0
) -> None:
"""
Process player action for specific hand

Args:
player: The player taking action
action: Action to perform (hit, stand, double, split, etc.)
hand_index: Index of the hand to act upon
"""
if hand_index >= len(self.player_hands[player]):
return

current_hand = self.player_hands[player][hand_index]

match action:
case "hit":
self.deal_card_to_hand(current_hand)
if current_hand.calculate_value() == -1: # Bust
current_hand.status = GameResult.BUST

case "stand":
current_hand.status = GameResult.ACTIVE

case "double":
if player.can_place_bet(current_hand.wager):
player.place_bet(current_hand.wager)
current_hand.double_wager()
self.deal_card_to_hand(current_hand)
current_hand.status = GameResult.ACTIVE

case "split":
self.split_hand(player, hand_index)

case "surrender":
player.adjust_bankroll(current_hand.wager // 2)
current_hand.surrender()
Loading