blackjack-cli 1.0.2__tar.gz → 1.1.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {blackjack_cli-1.0.2 → blackjack_cli-1.1.0}/PKG-INFO +1 -1
- {blackjack_cli-1.0.2 → blackjack_cli-1.1.0}/pyproject.toml +8 -1
- blackjack_cli-1.1.0/src/blackjack_cli/__init__.py +5 -0
- {blackjack_cli-1.0.2 → blackjack_cli-1.1.0/src}/blackjack_cli/blackjack.py +16 -17
- {blackjack_cli-1.0.2 → blackjack_cli-1.1.0/src}/blackjack_cli/config.py +1 -1
- blackjack_cli-1.1.0/src/deck/__init__.py +5 -0
- blackjack_cli-1.1.0/src/deck/card.py +49 -0
- blackjack_cli-1.1.0/src/deck/cardhand.py +46 -0
- blackjack_cli-1.1.0/src/deck/deck.py +73 -0
- blackjack_cli-1.0.2/blackjack_cli/__init__.py +0 -2
- {blackjack_cli-1.0.2 → blackjack_cli-1.1.0}/README.md +0 -0
- {blackjack_cli-1.0.2 → blackjack_cli-1.1.0/src}/blackjack_cli/console.py +0 -0
- {blackjack_cli-1.0.2 → blackjack_cli-1.1.0/src}/blackjack_cli/models/__init__.py +0 -0
- {blackjack_cli-1.0.2 → blackjack_cli-1.1.0/src}/blackjack_cli/models/stats_model.py +0 -0
- {blackjack_cli-1.0.2 → blackjack_cli-1.1.0/src}/blackjack_cli/stats.py +0 -0
|
@@ -1,11 +1,15 @@
|
|
|
1
1
|
[tool.poetry]
|
|
2
2
|
name = "blackjack-cli"
|
|
3
|
-
version = "1.0
|
|
3
|
+
version = "1.1.0"
|
|
4
4
|
description = "This is a cli-based blackjack game! Woo!"
|
|
5
5
|
authors = ["Vlek <derek@mccammond.org>"]
|
|
6
6
|
license = "GPLv3"
|
|
7
7
|
readme = "README.md"
|
|
8
8
|
repository = "https://github.com/vlek/blackjack-cli"
|
|
9
|
+
packages = [
|
|
10
|
+
{ include = "blackjack_cli", from = "src" },
|
|
11
|
+
{ include = "deck", from = "src" },
|
|
12
|
+
]
|
|
9
13
|
|
|
10
14
|
[tool.poetry.dependencies]
|
|
11
15
|
python = "^3.10"
|
|
@@ -42,3 +46,6 @@ fail_under = 90
|
|
|
42
46
|
[build-system]
|
|
43
47
|
requires = ["poetry-core"]
|
|
44
48
|
build-backend = "poetry.core.masonry.api"
|
|
49
|
+
|
|
50
|
+
[flake8]
|
|
51
|
+
max-line-length = 88
|
|
@@ -8,9 +8,10 @@ This is going to house things like:
|
|
|
8
8
|
"""
|
|
9
9
|
|
|
10
10
|
from enum import Enum
|
|
11
|
+
|
|
11
12
|
from typing_extensions import Self
|
|
12
13
|
|
|
13
|
-
from deck import
|
|
14
|
+
from deck import Card, CardHand, Deck
|
|
14
15
|
|
|
15
16
|
|
|
16
17
|
def blackjackScoringStrategy(cards: list[Card]) -> int:
|
|
@@ -100,28 +101,26 @@ class Blackjack:
|
|
|
100
101
|
|
|
101
102
|
def performDealersTurn(self) -> Self:
|
|
102
103
|
"""Performs the dealer's moves and finishes the game."""
|
|
103
|
-
|
|
104
|
-
|
|
104
|
+
while self.dealersCards.getScore() <= 16:
|
|
105
|
+
self._drawCard(self.dealersCards)
|
|
105
106
|
|
|
106
|
-
|
|
107
|
-
if playersScore > 21 or dealersScore == 21:
|
|
108
|
-
self.gameState = GameState.Lose
|
|
109
|
-
return self
|
|
107
|
+
self._calcGameState()
|
|
110
108
|
|
|
111
|
-
|
|
112
|
-
self._drawCard(self.dealersCards)
|
|
109
|
+
return self
|
|
113
110
|
|
|
114
|
-
|
|
111
|
+
def _calcGameState(self) -> None:
|
|
112
|
+
"""Based on current cards, calculates the gamestate."""
|
|
113
|
+
playersScore: int = self.playersCards.getScore()
|
|
114
|
+
dealersScore: int = self.dealersCards.getScore()
|
|
115
115
|
|
|
116
|
-
if playersScore >
|
|
116
|
+
if playersScore > 21:
|
|
117
|
+
self.gameState = GameState.Lose
|
|
118
|
+
elif playersScore == dealersScore:
|
|
119
|
+
self.gameState = GameState.Push
|
|
120
|
+
elif playersScore > dealersScore or dealersScore > 21:
|
|
117
121
|
self.gameState = GameState.Win
|
|
118
122
|
else:
|
|
119
|
-
|
|
120
|
-
self.gameState = GameState.Push
|
|
121
|
-
else:
|
|
122
|
-
self.gameState = GameState.Lose
|
|
123
|
-
|
|
124
|
-
return self
|
|
123
|
+
self.gameState = GameState.Lose
|
|
125
124
|
|
|
126
125
|
def _drawCard(self, hand: CardHand) -> Card | None:
|
|
127
126
|
"""Draws a card and places it into the given hand."""
|
|
@@ -31,7 +31,7 @@ class Config:
|
|
|
31
31
|
self.config_folder_path: Path = self.config_file_path.parent
|
|
32
32
|
|
|
33
33
|
if not self.config_folder_path.exists():
|
|
34
|
-
self.config_folder_path.mkdir()
|
|
34
|
+
self.config_folder_path.mkdir(parents=True)
|
|
35
35
|
|
|
36
36
|
if self.config_file_path.exists():
|
|
37
37
|
with self.config_file_path.open() as config_file:
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Handles the logic for a single Card within a Deck.
|
|
3
|
+
"""
|
|
4
|
+
|
|
5
|
+
from enum import Enum
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
class Card:
|
|
9
|
+
class Suit(Enum):
|
|
10
|
+
SPADES = "♠"
|
|
11
|
+
CLUBS = "♣"
|
|
12
|
+
DIAMONDS = "♦"
|
|
13
|
+
HEARTS = "♥"
|
|
14
|
+
|
|
15
|
+
class Value(Enum):
|
|
16
|
+
TWO = 2
|
|
17
|
+
THREE = 3
|
|
18
|
+
FOUR = 4
|
|
19
|
+
FIVE = 5
|
|
20
|
+
SIX = 6
|
|
21
|
+
SEVEN = 7
|
|
22
|
+
EIGHT = 8
|
|
23
|
+
NINE = 9
|
|
24
|
+
TEN = 10
|
|
25
|
+
JACK = "J"
|
|
26
|
+
QUEEN = "Q"
|
|
27
|
+
KING = "K"
|
|
28
|
+
ACE = "A"
|
|
29
|
+
|
|
30
|
+
def __init__(self, suit: Suit, value: Value) -> None:
|
|
31
|
+
self.suit = suit
|
|
32
|
+
self.value = value
|
|
33
|
+
|
|
34
|
+
def __str__(self) -> str:
|
|
35
|
+
"""Returns the string representation of a Card."""
|
|
36
|
+
return f"{self.suit.value}{self.value.value}"
|
|
37
|
+
|
|
38
|
+
def __eq__(self, otherCard) -> bool:
|
|
39
|
+
"""Determine whether one card is the same as the other."""
|
|
40
|
+
return self.suit == otherCard.suit and self.value == otherCard.value
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
if __name__ == "__main__":
|
|
44
|
+
card = Card(Card.Suit.SPADES, Card.Value.ACE)
|
|
45
|
+
otherCard = Card(Card.Suit.SPADES, Card.Value.ACE)
|
|
46
|
+
|
|
47
|
+
print(card)
|
|
48
|
+
|
|
49
|
+
print(card == otherCard)
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
"""
|
|
2
|
+
This deals with holding and evaluating cards that
|
|
3
|
+
a player has in their hand.
|
|
4
|
+
"""
|
|
5
|
+
|
|
6
|
+
from typing import Callable
|
|
7
|
+
|
|
8
|
+
from typing_extensions import Self
|
|
9
|
+
|
|
10
|
+
from deck import Card
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
class CardHand:
|
|
14
|
+
|
|
15
|
+
def __init__(
|
|
16
|
+
self,
|
|
17
|
+
cards: list[Card | None],
|
|
18
|
+
scoringStrategy: Callable[[list[Card]], int] = lambda x: -1,
|
|
19
|
+
) -> None:
|
|
20
|
+
"""Initializes a cardhand."""
|
|
21
|
+
|
|
22
|
+
self.cards: list[Card] = [c for c in cards if c is not None]
|
|
23
|
+
self.scoringStrategy = scoringStrategy
|
|
24
|
+
|
|
25
|
+
def setScoringStrategy(self, scoringStrategy: Callable[[list[Card]], int]) -> Self:
|
|
26
|
+
"""Sets the strategy for how to score the given hand."""
|
|
27
|
+
self.scoringStrategy = scoringStrategy
|
|
28
|
+
return self
|
|
29
|
+
|
|
30
|
+
def getScore(self) -> int:
|
|
31
|
+
"""Returns the score of the current hand with the given strategy."""
|
|
32
|
+
return self.scoringStrategy(self.cards)
|
|
33
|
+
|
|
34
|
+
def add(self, card: Card | None) -> Self:
|
|
35
|
+
"""Add a card to the player's hand."""
|
|
36
|
+
if card is not None:
|
|
37
|
+
self.cards.append(card)
|
|
38
|
+
return self
|
|
39
|
+
|
|
40
|
+
def __str__(self) -> str:
|
|
41
|
+
"""Returns string representation of the cardhand."""
|
|
42
|
+
return " ".join(str(c) for c in self.cards)
|
|
43
|
+
|
|
44
|
+
def __len__(self) -> int:
|
|
45
|
+
"""Returns the length of a given hand."""
|
|
46
|
+
return len(self.cards)
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Logic for having a deck of cards.
|
|
3
|
+
|
|
4
|
+
NOTE: THIS DOES NOT NECESSARILY HAVE ANYTHING TO DO WITH BLACKJACK!
|
|
5
|
+
|
|
6
|
+
We have 52 cards:
|
|
7
|
+
4 Suits:
|
|
8
|
+
Clubs, Spades, Hearts, Diamonds
|
|
9
|
+
|
|
10
|
+
9 Number cards:
|
|
11
|
+
2 - 10
|
|
12
|
+
|
|
13
|
+
3 Face cards:
|
|
14
|
+
Jack
|
|
15
|
+
Queen
|
|
16
|
+
King
|
|
17
|
+
|
|
18
|
+
1 Ace
|
|
19
|
+
"""
|
|
20
|
+
|
|
21
|
+
from deck import Card
|
|
22
|
+
from typing_extensions import Self
|
|
23
|
+
from random import randint
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
class Deck:
|
|
27
|
+
def __init__(self) -> None:
|
|
28
|
+
self.cards: list[Card] = []
|
|
29
|
+
self.isShuffled = False
|
|
30
|
+
self.__add_cards()
|
|
31
|
+
|
|
32
|
+
def shuffle(self) -> Self:
|
|
33
|
+
"""Returns the deck of cards shuffled."""
|
|
34
|
+
self.isShuffled = True
|
|
35
|
+
return self
|
|
36
|
+
|
|
37
|
+
def draw(self) -> Card | None:
|
|
38
|
+
"""Returns a card from the deck."""
|
|
39
|
+
result: Card | None
|
|
40
|
+
|
|
41
|
+
if len(self.cards) == 0:
|
|
42
|
+
result = None
|
|
43
|
+
elif self.isShuffled:
|
|
44
|
+
cardChoice: int = randint(0, len(self.cards) - 1)
|
|
45
|
+
result = self.cards.pop(cardChoice)
|
|
46
|
+
else:
|
|
47
|
+
result = self.cards.pop()
|
|
48
|
+
|
|
49
|
+
return result
|
|
50
|
+
|
|
51
|
+
def __add__(self, otherDeck: Self) -> Self:
|
|
52
|
+
"""Puts to decks of cards together."""
|
|
53
|
+
self.cards += otherDeck.cards
|
|
54
|
+
|
|
55
|
+
return self
|
|
56
|
+
|
|
57
|
+
def __len__(self) -> int:
|
|
58
|
+
"""Returns the number of cards in the deck."""
|
|
59
|
+
return len(self.cards)
|
|
60
|
+
|
|
61
|
+
def __mul__(self, num: int) -> Self:
|
|
62
|
+
"""Duplicates the cards in the deck num times."""
|
|
63
|
+
self.cards *= num
|
|
64
|
+
|
|
65
|
+
return self
|
|
66
|
+
|
|
67
|
+
def __add_cards(self) -> Self:
|
|
68
|
+
"""Adds initial cards to the deck."""
|
|
69
|
+
for suit in Card.Suit:
|
|
70
|
+
for value in Card.Value:
|
|
71
|
+
self.cards.append(Card(suit, value))
|
|
72
|
+
|
|
73
|
+
return self
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|