maverick 0.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.
Files changed (42) hide show
  1. maverick-0.1.0/PKG-INFO +93 -0
  2. maverick-0.1.0/README.md +80 -0
  3. maverick-0.1.0/pyproject.toml +52 -0
  4. maverick-0.1.0/src/maverick/__init__.py +53 -0
  5. maverick-0.1.0/src/maverick/_registered_players.py +7 -0
  6. maverick-0.1.0/src/maverick/card.py +108 -0
  7. maverick-0.1.0/src/maverick/deck.py +144 -0
  8. maverick-0.1.0/src/maverick/enums.py +342 -0
  9. maverick-0.1.0/src/maverick/eventbus.py +117 -0
  10. maverick-0.1.0/src/maverick/events.py +58 -0
  11. maverick-0.1.0/src/maverick/game.py +1100 -0
  12. maverick-0.1.0/src/maverick/hand.py +72 -0
  13. maverick-0.1.0/src/maverick/holding.py +87 -0
  14. maverick-0.1.0/src/maverick/player.py +119 -0
  15. maverick-0.1.0/src/maverick/playeraction.py +39 -0
  16. maverick-0.1.0/src/maverick/players/__init__.py +41 -0
  17. maverick-0.1.0/src/maverick/players/agressivebot.py +53 -0
  18. maverick-0.1.0/src/maverick/players/archetypes/__init__.py +33 -0
  19. maverick-0.1.0/src/maverick/players/archetypes/abc.py +95 -0
  20. maverick-0.1.0/src/maverick/players/archetypes/bully.py +94 -0
  21. maverick-0.1.0/src/maverick/players/archetypes/fish.py +91 -0
  22. maverick-0.1.0/src/maverick/players/archetypes/grinder.py +88 -0
  23. maverick-0.1.0/src/maverick/players/archetypes/gto.py +99 -0
  24. maverick-0.1.0/src/maverick/players/archetypes/hero_caller.py +88 -0
  25. maverick-0.1.0/src/maverick/players/archetypes/loose_aggressive.py +87 -0
  26. maverick-0.1.0/src/maverick/players/archetypes/loose_passive.py +45 -0
  27. maverick-0.1.0/src/maverick/players/archetypes/maniac.py +75 -0
  28. maverick-0.1.0/src/maverick/players/archetypes/scared_money.py +84 -0
  29. maverick-0.1.0/src/maverick/players/archetypes/shark.py +101 -0
  30. maverick-0.1.0/src/maverick/players/archetypes/tight_agressive.py +95 -0
  31. maverick-0.1.0/src/maverick/players/archetypes/tight_passive.py +72 -0
  32. maverick-0.1.0/src/maverick/players/archetypes/tilted.py +95 -0
  33. maverick-0.1.0/src/maverick/players/archetypes/whale.py +77 -0
  34. maverick-0.1.0/src/maverick/players/callbot.py +17 -0
  35. maverick-0.1.0/src/maverick/players/foldbot.py +17 -0
  36. maverick-0.1.0/src/maverick/playerstate.py +45 -0
  37. maverick-0.1.0/src/maverick/protocol.py +93 -0
  38. maverick-0.1.0/src/maverick/rules.py +142 -0
  39. maverick-0.1.0/src/maverick/state.py +164 -0
  40. maverick-0.1.0/src/maverick/utils/__init__.py +8 -0
  41. maverick-0.1.0/src/maverick/utils/holding_strength.py +93 -0
  42. maverick-0.1.0/src/maverick/utils/scoring.py +262 -0
@@ -0,0 +1,93 @@
1
+ Metadata-Version: 2.3
2
+ Name: maverick
3
+ Version: 0.1.0
4
+ Summary: Utilities for a poker-playing assistant
5
+ Author: Bence Balogh
6
+ Author-email: Bence Balogh <benceeok@gmail.com>
7
+ License: MIT
8
+ Requires-Dist: pydantic>=2.12.5
9
+ Requires-Python: >=3.12
10
+ Project-URL: Homepage, https://github.com/BALOGHBence/maverick
11
+ Project-URL: Documentation, https://pymaverick.readthedocs.io/en/latest/index.html
12
+ Description-Content-Type: text/markdown
13
+
14
+ <div align="center">
15
+ <p>
16
+ <a href="https://readthedocs.org/projects/pymaverick/badge/?version=latest)](https://pymaverick.readthedocs.io/en/latest/?badge=latest" target="_blank">
17
+ <img width="100%" src="https://github.com/BALOGHBence/maverick/blob/main/cover_image.png?raw=true" alt="Maverick banner"></a>
18
+ </p>
19
+
20
+ <div>
21
+ <a href="https://pymaverick.readthedocs.io/en/latest/?badge=latest"><img src="https://readthedocs.org/projects/pymaverick/badge/?version=latest" alt="Documentation Status"></a>
22
+ <a href="https://codecov.io/gh/BALOGHBence/maverick"><img src="https://codecov.io/gh/BALOGHBence/maverick/graph/badge.svg?token=VDRFOUJYUG" alt="Code Coverage"></a>
23
+ <a href="https://app.codacy.com/gh/BALOGHBence/maverick/dashboard?utm_source=gh&utm_medium=referral&utm_content=&utm_campaign=Badge_grade"><img src="https://app.codacy.com/project/badge/Grade/c960167518b646eea31cf1ff02a13823" alt="Code Quality"></a>
24
+ <a href="https://github.com/psf/black"><img src="https://img.shields.io/badge/code%20style-black-000000.svg" alt="Code Style"></a>
25
+ <a href="https://opensource.org/licenses/MIT"><img src="https://img.shields.io/badge/License-MIT-yellow.svg" alt="License"></a>
26
+ </div>
27
+
28
+ <br>
29
+
30
+ <div>
31
+ <a href="https://pymaverick.readthedocs.io/en/latest/index.html"><img src="https://img.shields.io/badge/Documentation-blue?style=flat" alt="Documentation"></a>
32
+ </div>
33
+
34
+ <br>
35
+
36
+ <div>
37
+ <a href="https://buymeacoffee.com/benceeokf"><img src="https://img.shields.io/badge/Buy%20Me%20a%20Coffee-ffdd00?style=for-the-badge&logo=buy-me-a-coffee&logoColor=black" alt="BuyMeACoffee"></a>
38
+ </div>
39
+
40
+ <br>
41
+
42
+ <p>
43
+ A Python library for simulating poker games with custom player strategies.
44
+ </p>
45
+
46
+ </div>
47
+
48
+ > **Note**
49
+ >
50
+ > Maverick is under active development and subject to change.
51
+ > First deployment to PyPI is going to be announced on
52
+ > [my LinkedIn profile](https://www.linkedin.com/in/bence-balogh-082073181/).
53
+
54
+ ## Highlights
55
+
56
+ - **Configurable Poker Games**: Full rules and mechanics supporting a variety of flavours
57
+ - **State Machine Architecture**: Clean separation of game states and transitions
58
+ - **Flexible Player System**: Protocol-based player interface for custom implementations
59
+ - **Hand Evaluation**: Built-in poker hand scoring and comparison
60
+ - **Event System**: Track all game events for analysis and replay
61
+ - **Well Documented**: Comprehensive documentation of rules and APIs
62
+ - **Thoroughly Tested**: Features are heavily tested with high code coverage
63
+
64
+ ## Documentation
65
+
66
+ The project has extensive [documentation](https://pymaverick.readthedocs.io/en/latest/index.html) hosted on ReadTheDocs. Most library information is documented there, with only the essentials kept here.
67
+
68
+ ## Versioning
69
+
70
+ The project adheres to [semantic versioning](https://semver.org/).
71
+
72
+ ## Contributing
73
+
74
+ Contributions are currently expected in any the following ways:
75
+
76
+ - **finding bugs**
77
+ If you run into trouble when using the library and you think it is a bug, feel free to raise an issue.
78
+ - **feedback**
79
+ All kinds of ideas are welcome. For instance if you feel like something is still shady (after reading the user guide), we want to know. Be gentle though, the development of the library is financially not supported yet.
80
+ - **feature requests**
81
+ Tell us what you think is missing (with realistic expectations).
82
+ - **examples**
83
+ If you've done something with the library and you think that it would make for a good example, get in touch with the developers and we will happily inlude it in the documention.
84
+ - **funding**
85
+ Use one of the supported funding channels. Any amount you can afford is appreciated.
86
+ - **sharing is caring**
87
+ If you like the library, share it with your friends or colleagues so they can like it too.
88
+
89
+ In all cases, read the [contributing guidelines](CONTRIBUTING.md) before you do anything.
90
+
91
+ ## License
92
+
93
+ This package is licensed under the [MIT license](LICENSE.txt).
@@ -0,0 +1,80 @@
1
+ <div align="center">
2
+ <p>
3
+ <a href="https://readthedocs.org/projects/pymaverick/badge/?version=latest)](https://pymaverick.readthedocs.io/en/latest/?badge=latest" target="_blank">
4
+ <img width="100%" src="https://github.com/BALOGHBence/maverick/blob/main/cover_image.png?raw=true" alt="Maverick banner"></a>
5
+ </p>
6
+
7
+ <div>
8
+ <a href="https://pymaverick.readthedocs.io/en/latest/?badge=latest"><img src="https://readthedocs.org/projects/pymaverick/badge/?version=latest" alt="Documentation Status"></a>
9
+ <a href="https://codecov.io/gh/BALOGHBence/maverick"><img src="https://codecov.io/gh/BALOGHBence/maverick/graph/badge.svg?token=VDRFOUJYUG" alt="Code Coverage"></a>
10
+ <a href="https://app.codacy.com/gh/BALOGHBence/maverick/dashboard?utm_source=gh&utm_medium=referral&utm_content=&utm_campaign=Badge_grade"><img src="https://app.codacy.com/project/badge/Grade/c960167518b646eea31cf1ff02a13823" alt="Code Quality"></a>
11
+ <a href="https://github.com/psf/black"><img src="https://img.shields.io/badge/code%20style-black-000000.svg" alt="Code Style"></a>
12
+ <a href="https://opensource.org/licenses/MIT"><img src="https://img.shields.io/badge/License-MIT-yellow.svg" alt="License"></a>
13
+ </div>
14
+
15
+ <br>
16
+
17
+ <div>
18
+ <a href="https://pymaverick.readthedocs.io/en/latest/index.html"><img src="https://img.shields.io/badge/Documentation-blue?style=flat" alt="Documentation"></a>
19
+ </div>
20
+
21
+ <br>
22
+
23
+ <div>
24
+ <a href="https://buymeacoffee.com/benceeokf"><img src="https://img.shields.io/badge/Buy%20Me%20a%20Coffee-ffdd00?style=for-the-badge&logo=buy-me-a-coffee&logoColor=black" alt="BuyMeACoffee"></a>
25
+ </div>
26
+
27
+ <br>
28
+
29
+ <p>
30
+ A Python library for simulating poker games with custom player strategies.
31
+ </p>
32
+
33
+ </div>
34
+
35
+ > **Note**
36
+ >
37
+ > Maverick is under active development and subject to change.
38
+ > First deployment to PyPI is going to be announced on
39
+ > [my LinkedIn profile](https://www.linkedin.com/in/bence-balogh-082073181/).
40
+
41
+ ## Highlights
42
+
43
+ - **Configurable Poker Games**: Full rules and mechanics supporting a variety of flavours
44
+ - **State Machine Architecture**: Clean separation of game states and transitions
45
+ - **Flexible Player System**: Protocol-based player interface for custom implementations
46
+ - **Hand Evaluation**: Built-in poker hand scoring and comparison
47
+ - **Event System**: Track all game events for analysis and replay
48
+ - **Well Documented**: Comprehensive documentation of rules and APIs
49
+ - **Thoroughly Tested**: Features are heavily tested with high code coverage
50
+
51
+ ## Documentation
52
+
53
+ The project has extensive [documentation](https://pymaverick.readthedocs.io/en/latest/index.html) hosted on ReadTheDocs. Most library information is documented there, with only the essentials kept here.
54
+
55
+ ## Versioning
56
+
57
+ The project adheres to [semantic versioning](https://semver.org/).
58
+
59
+ ## Contributing
60
+
61
+ Contributions are currently expected in any the following ways:
62
+
63
+ - **finding bugs**
64
+ If you run into trouble when using the library and you think it is a bug, feel free to raise an issue.
65
+ - **feedback**
66
+ All kinds of ideas are welcome. For instance if you feel like something is still shady (after reading the user guide), we want to know. Be gentle though, the development of the library is financially not supported yet.
67
+ - **feature requests**
68
+ Tell us what you think is missing (with realistic expectations).
69
+ - **examples**
70
+ If you've done something with the library and you think that it would make for a good example, get in touch with the developers and we will happily inlude it in the documention.
71
+ - **funding**
72
+ Use one of the supported funding channels. Any amount you can afford is appreciated.
73
+ - **sharing is caring**
74
+ If you like the library, share it with your friends or colleagues so they can like it too.
75
+
76
+ In all cases, read the [contributing guidelines](CONTRIBUTING.md) before you do anything.
77
+
78
+ ## License
79
+
80
+ This package is licensed under the [MIT license](LICENSE.txt).
@@ -0,0 +1,52 @@
1
+ [project]
2
+ name = "maverick"
3
+ version = "0.1.0"
4
+ description = "Utilities for a poker-playing assistant"
5
+ readme = "README.md"
6
+ authors = [
7
+ { name = "Bence Balogh", email = "benceeok@gmail.com" }
8
+ ]
9
+ license = { text = "MIT" }
10
+ requires-python = ">=3.12"
11
+ dependencies = [
12
+ "pydantic>=2.12.5",
13
+ ]
14
+
15
+ [dependency-groups]
16
+ docs = [
17
+ "linkify-it-py>=2.0.3",
18
+ "myst-nb>=1.3.0",
19
+ "myst-parser>=5.0.0",
20
+ "sphinx>=9.1.0",
21
+ "sphinx-book-theme>=1.1.3",
22
+ "sphinx-copybutton>=0.5.2",
23
+ ]
24
+ test = [
25
+ "pandas>=2.3.3",
26
+ "pytest>=9.0.2",
27
+ "pytest-cov>=7.0.0",
28
+ ]
29
+ dev = [
30
+ {include-group = "test"},
31
+ {include-group = "docs"},
32
+ "black>=25.12.0",
33
+ "ipykernel>=7.1.0",
34
+ "matplotlib>=3.10.8",
35
+ "scipy>=1.16.3",
36
+ ]
37
+
38
+ [project.urls]
39
+ Homepage = "https://github.com/BALOGHBence/maverick"
40
+ Documentation = "https://pymaverick.readthedocs.io/en/latest/index.html"
41
+
42
+ [tool.pytest.ini_options]
43
+ testpaths = ["tests"]
44
+ addopts = "-q"
45
+
46
+ [build-system]
47
+ requires = ["uv_build>=0.9.22,<0.10.0"]
48
+ build-backend = "uv_build"
49
+
50
+ [tool.uv.build-backend]
51
+ module-name = "maverick"
52
+ module-root = "src"
@@ -0,0 +1,53 @@
1
+ from importlib.metadata import metadata
2
+
3
+ from .card import Card
4
+ from .deck import Deck
5
+ from .enums import (
6
+ Suit,
7
+ Rank,
8
+ HandType,
9
+ Street,
10
+ PlayerStateType,
11
+ GameStateType,
12
+ ActionType,
13
+ GameEventType,
14
+ )
15
+ from .player import Player
16
+ from .hand import Hand
17
+ from .holding import Holding
18
+ from .utils.scoring import score_hand
19
+ from .game import Game
20
+ from .state import GameState
21
+ from .protocol import PlayerLike
22
+ from .playeraction import PlayerAction
23
+ from .playerstate import PlayerState
24
+ from .events import GameEvent
25
+
26
+ __all__ = [
27
+ "Card",
28
+ "Deck",
29
+ "Suit",
30
+ "Rank",
31
+ "HandType",
32
+ "Street",
33
+ "PlayerStateType",
34
+ "Player",
35
+ "Hand",
36
+ "Holding",
37
+ "score_hand",
38
+ "Game",
39
+ "GameState",
40
+ "GameEventType",
41
+ "GameStateType",
42
+ "ActionType",
43
+ "PlayerLike",
44
+ "PlayerAction",
45
+ "PlayerState",
46
+ "GameEvent",
47
+ ]
48
+
49
+ __pkg_name__ = "maverick"
50
+ __pkg_metadata__ = metadata(__pkg_name__)
51
+ __version__ = __pkg_metadata__["version"]
52
+ __description__ = __pkg_metadata__["summary"]
53
+ del __pkg_metadata__
@@ -0,0 +1,7 @@
1
+ from collections import defaultdict
2
+
3
+ from .protocol import PlayerLike
4
+
5
+ __all__ = ["registered_players"]
6
+
7
+ registered_players: dict[str, PlayerLike] = defaultdict(lambda: None)
@@ -0,0 +1,108 @@
1
+ import random
2
+ from typing import Tuple
3
+
4
+ from pydantic import BaseModel
5
+
6
+ from .enums import Suit, Rank, HandType
7
+ from .utils.scoring import score_hand
8
+
9
+
10
+ __all__ = ["Card"]
11
+
12
+
13
+ class Card(BaseModel):
14
+ """A playing card with a suit and rank.
15
+
16
+ Fields
17
+ ------
18
+ suit : Suit
19
+ The suit of the card (Hearts, Diamonds, Clubs, Spades).
20
+ rank : Rank
21
+ The rank of the card (Two through Ace).
22
+
23
+ Examples
24
+ --------
25
+ >>> from maverick import Card, Suit, Rank
26
+ >>> card = Card(suit=Suit.HEARTS, rank=Rank.ACE)
27
+ >>> card.utf8()
28
+ 'A♥'
29
+ """
30
+
31
+ suit: Suit
32
+ rank: Rank
33
+
34
+ @classmethod
35
+ def random(cls, n: int = 1) -> list["Card"]:
36
+ """Generate n random cards without repetition."""
37
+ suits = list(Suit)
38
+ ranks = list(Rank)
39
+ all_cards = [cls(suit=s, rank=r) for s in suits for r in ranks]
40
+ selected = random.sample(all_cards, n)
41
+ return selected if n > 1 else selected[0]
42
+
43
+ def score(self) -> Tuple[HandType, float]:
44
+ """Classifies and scores the card.
45
+
46
+ Returns (HandType, float_score) where higher scores = stronger hands.
47
+ """
48
+ return score_hand([self])
49
+
50
+ def utf8(self) -> str:
51
+ """Return the UTF-8 representation of the card."""
52
+ suit_symbols = {
53
+ Suit.HEARTS: "♥",
54
+ Suit.SPADES: "♠",
55
+ Suit.CLUBS: "♣",
56
+ Suit.DIAMONDS: "♦",
57
+ }
58
+ rank_symbols = {
59
+ Rank.TWO: "2",
60
+ Rank.THREE: "3",
61
+ Rank.FOUR: "4",
62
+ Rank.FIVE: "5",
63
+ Rank.SIX: "6",
64
+ Rank.SEVEN: "7",
65
+ Rank.EIGHT: "8",
66
+ Rank.NINE: "9",
67
+ Rank.TEN: "10",
68
+ Rank.JACK: "J",
69
+ Rank.QUEEN: "Q",
70
+ Rank.KING: "K",
71
+ Rank.ACE: "A",
72
+ }
73
+ return f"{rank_symbols[self.rank]}{suit_symbols[self.suit]}"
74
+
75
+ def code(self) -> str:
76
+ """Return short canonical card code (e.g. Ah, Td, Ks)."""
77
+ rank_codes = {
78
+ Rank.TWO: "2",
79
+ Rank.THREE: "3",
80
+ Rank.FOUR: "4",
81
+ Rank.FIVE: "5",
82
+ Rank.SIX: "6",
83
+ Rank.SEVEN: "7",
84
+ Rank.EIGHT: "8",
85
+ Rank.NINE: "9",
86
+ Rank.TEN: "T",
87
+ Rank.JACK: "J",
88
+ Rank.QUEEN: "Q",
89
+ Rank.KING: "K",
90
+ Rank.ACE: "A",
91
+ }
92
+ suit_codes = {
93
+ Suit.HEARTS: "h",
94
+ Suit.DIAMONDS: "d",
95
+ Suit.CLUBS: "c",
96
+ Suit.SPADES: "s",
97
+ }
98
+ return f"{rank_codes[self.rank]}{suit_codes[self.suit]}"
99
+
100
+ def text(self) -> str:
101
+ """Return human-readable text representation."""
102
+ return f"{self.rank.name.title()} of {self.suit.name.title()}"
103
+
104
+ def __repr__(self) -> str:
105
+ return f"Card({self.code()})"
106
+
107
+ def __str__(self) -> str:
108
+ return self.utf8()
@@ -0,0 +1,144 @@
1
+ from warnings import warn
2
+ import random
3
+
4
+ from pydantic import BaseModel
5
+
6
+ from .enums import Suit, Rank
7
+ from .card import Card
8
+
9
+ __all__ = ["Deck"]
10
+
11
+
12
+ class Deck(BaseModel):
13
+ """A standard deck of 52 playing cards.
14
+
15
+ Fields
16
+ ------
17
+ cards : list[Card]
18
+ The list of cards in the deck.
19
+
20
+ Examples
21
+ --------
22
+ >>> from maverick import Deck
23
+ >>> deck = Deck.standard_deck(shuffle=True)
24
+ >>> dealt_cards = deck.deal(5)
25
+ >>> len(dealt_cards)
26
+ 5
27
+ >>> len(deck.cards)
28
+ 47
29
+ """
30
+
31
+ cards: list[Card]
32
+
33
+ @classmethod
34
+ def build(cls, shuffle: bool = False) -> "Deck":
35
+ """Build a standard deck of 52 cards.
36
+
37
+ Parameters
38
+ ----------
39
+ shuffle : bool, optional
40
+ Whether to shuffle the deck after building (default is False).
41
+ """
42
+ ranks = list(Rank)
43
+ suits = list(Suit)
44
+ cards = []
45
+
46
+ for rank in ranks:
47
+ for suit in suits:
48
+ card = Card(suit=suit, rank=rank)
49
+ cards.append(card)
50
+
51
+ deck = cls(cards=cards)
52
+
53
+ if shuffle:
54
+ deck.shuffle()
55
+
56
+ return deck
57
+
58
+ @classmethod
59
+ def standard_deck(cls, shuffle: bool = False) -> "Deck":
60
+ """Create and optionally shuffle a standard deck of 52 cards.
61
+
62
+ This is an alias for Deck.build() for clarity.
63
+
64
+ Parameters
65
+ ----------
66
+ shuffle : bool, optional
67
+ Whether to shuffle the deck after building (default is False).
68
+ """
69
+ return cls.build(shuffle=shuffle)
70
+
71
+ def deal(self, n: int) -> list[Card]:
72
+ """
73
+ Deal n random cards from the deck.
74
+
75
+ Parameters
76
+ ----------
77
+ n : int
78
+ The number of cards to deal.
79
+
80
+ Returns
81
+ -------
82
+ list[Card]
83
+ The list of dealt cards.
84
+
85
+ Raises
86
+ ------
87
+ ValueError
88
+ If there are not enough cards in the deck to deal.
89
+
90
+ Notes
91
+ -----
92
+ 1) Dealt cards are removed from the deck.
93
+ 2) If n <= 0, an empty list is returned.
94
+ """
95
+ if n > len(self.cards):
96
+ raise ValueError("Not enough cards in the deck to deal.")
97
+
98
+ if n <= 0:
99
+ warn(
100
+ "Requested to deal non-positive number of cards; returning empty list."
101
+ )
102
+ return []
103
+
104
+ dealt_cards = random.sample(self.cards, n)
105
+
106
+ for card in dealt_cards:
107
+ self.cards.remove(card)
108
+
109
+ return dealt_cards
110
+
111
+ def shuffle(self, n: int = 1) -> "Deck":
112
+ """Shuffle the deck of cards n times.
113
+
114
+ Parameters
115
+ ----------
116
+ n : int, optional
117
+ The number of times to shuffle the deck (default is 1).
118
+ """
119
+ if n <= 0:
120
+ warn("Number of shuffles must be positive; returning unshuffled deck.")
121
+ return self
122
+
123
+ for _ in range(n):
124
+ random.shuffle(self.cards)
125
+
126
+ return self
127
+
128
+ def missing_cards(self) -> list[Card]:
129
+ """Return the list of cards missing from the deck."""
130
+ full_deck = Deck.build()
131
+ missing = [card for card in full_deck.cards if card not in self.cards]
132
+ return missing
133
+
134
+ def remove_cards(self, cards_to_remove: list[Card]) -> None:
135
+ """Remove specified cards from the deck.
136
+
137
+ Parameters
138
+ ----------
139
+ cards_to_remove : list[Card]
140
+ The list of cards to remove from the deck.
141
+ """
142
+ for card in cards_to_remove:
143
+ if card in self.cards:
144
+ self.cards.remove(card)