clubs.poker package

Submodules

clubs.poker.card module

Classes and functions to create and manipulate cards and lists of cards from a standard 52 card poker deck

class clubs.poker.card.Card(string: str)[source]

Bases: object

Cards are represented as 32-bit integers. Most of the bits are used and have a specific meaning.

bitrank

suit

rank

prime

xxxbbbbbbbbbbbbb

cdhs

rrrr

xxpppppp

  1. p = prime number of rank (deuce=2,trey=3,four=5,…,ace=41)

  2. r = rank of card (deuce=0,trey=1,four=2,five=3,…,ace=12)

  3. cdhs = suit of card (bit turned on based on suit of card)

  4. b = bit turned on depending on rank of card

  5. x = unused

Parameters

string (str) – card string of format ‘{rank}{suit}’ where rank is from [2-9, T/t, J/j, Q/q, K/k, A/a] and suit is from [S/s, H/h, D/d, C/c]

Examples

>>> card = Card('TC')
>>> card = Card('7H')
>>> card = Card('ad')
class clubs.poker.card.Deck(num_suits: int, num_ranks: int)[source]

Bases: object

A deck contains at most 52 cards, 13 ranks 4 suits. Any “subdeck” of the standard 52 card deck is valid, i.e. the number of suits must be between 1 and 4 and number of ranks between 1 and 13. A deck can be tricked to ensure a certain order of cards.

Parameters
  • num_suits (int) – number of suits to use in deck

  • num_ranks (int) – number of ranks to use in deck

draw(n: int = 1)List[clubs.poker.card.Card][source]

Draws cards from the top of the deck. If the number of cards to draw exceeds the number of cards in the deck, all cards left in the deck are returned.

Parameters

n (int, optional) – number of cards to draw, by default 1

Returns

cards drawn from the deck

Return type

List[Card]

shuffle()clubs.poker.card.Deck[source]

Shuffles the deck. If a tricking order is given, the desired cards are placed on the top of the deck after shuffling.

Returns

self

Return type

Deck

trick(top_cards: List[clubs.poker.card.Card])clubs.poker.card.Deck[source]

Tricks the deck by placing a fixed order of cards on the top of the deck and shuffling the rest. E.g. deck.trick([Card(‘AS’), Card(‘2H’)]) places the ace of spades and deuce of hearts on the top of the deck.

Parameters

top_cards (Optional[List[Union[str, Card]]], optional) – list of cards to be placed on the top of the deck, by default None, by default None

Returns

self

Return type

Deck

untrick()clubs.poker.card.Deck[source]

Removes the tricked cards from the top of the deck.

Returns

self

Return type

Deck

clubs.poker.engine module

Classes and functions for running poker games

class clubs.poker.engine.Dealer(num_players: int, num_streets: int, blinds: Union[int, List[int]], antes: Union[int, List[int]], raise_sizes: Union[float, str, List[Union[float, str]]], num_raises: Union[float, List[float]], num_suits: int, num_ranks: int, num_hole_cards: int, num_community_cards: Union[int, List[int]], num_cards_for_hand: int, mandatory_num_hole_cards: int, start_stack: int, low_end_straight: bool = True, order: Optional[List[str]] = None)[source]

Bases: object

Runs a range of different of poker games dependent on the given configuration. Supports limit, no limit and pot limit bet sizing, arbitrary deck sizes, arbitrary hole and community cards and many other options.

Parameters
  • num_players (int) – maximum number of players

  • num_streets (int) – number of streets including preflop, e.g. for texas hold’em num_streets=4

  • blinds (Union[int, List[int]]) – blind distribution as a list of ints, one for each player starting from the button e.g. [0, 1, 2] for a three player game with a sb of 1 and bb of 2, passed ints will be expanded to all players i.e. pass blinds=0 for no blinds

  • antes (Union[int, List[int]]) – ante distribution as a list of ints, one for each player starting from the button e.g. [0, 0, 5] for a three player game with a bb ante of 5, passed ints will be expanded to all players i.e. pass antes=0 for no antes

  • raise_sizes (Union[float, str, List[Union[float, str]]]) – max raise sizes for each street, valid raise sizes are ints, floats, and ‘pot’, e.g. for a 1-2 limit hold’em the raise sizes should be [2, 2, 4, 4] as the small and big bet are 2 and 4. float(‘inf’) can be used for no limit games. pot limit raise sizes can be set using ‘pot’. if only a single int, float or string is passed the value is expanded to a list the length of number of streets, e.g. for a standard no limit game pass raise_sizes=float(‘inf’)

  • num_raises (Union[float, List[float]]) – max number of bets for each street including preflop, valid raise numbers are ints and floats. if only a single int or float is passed the value is expanded to a list the length of number of streets, e.g. for a standard limit game pass num_raises=4

  • num_suits (int) – number of suits to use in deck, must be between 1 and 4

  • num_ranks (int) – number of ranks to use in deck, must be between 1 and 13

  • num_hole_cards (int) – number of hole cards per player, must be greater than 0

  • num_community_cards (Union[int, List[int]]) – number of community cards per street including preflop, e.g. for texas hold’em pass num_community_cards=[0, 3, 1, 1]. if only a single int is passed, it is expanded to a list the length of number of streets

  • num_cards_for_hand (int) – number of cards for a valid poker hand, e.g. for texas hold’em num_cards_for_hand=5

  • mandatory_num_hole_cards (int) – number of hole cards which have to be used for the hand, e.g. for pot limit omaha mandatory_num_hole_cards=2

  • start_stack (int) – number of chips each player starts with

  • low_end_straight (bool, optional) – toggle to include the low ace straight within valid hands, by default True

  • order (Optional[List[str]], optional) – optional custom order of hand ranks, must be permutation of [‘sf’, ‘fk’, ‘fh’, ‘fl’, ‘st’, ‘tk’, ‘tp’, ‘pa’, ‘hc’]. if order=None, hands are ranked by rarity. by default None

Examples

>>> Dealer( # 1-2 Heads Up No Limit Texas Hold'em
...     num_players=2, num_streets=4, blinds=[1, 2], antes=0,
...     raise_sizes=float('inf'), num_raises=float('inf'),
...     num_suits=4, num_ranks=13, num_hole_cards=2,
...     mandatory_num_hole_cards=0, start_stack=200
... )
>>> Dealer( # 1-2 6 Player PLO
...     num_players=6, num_streets=4, blinds=[0, 1, 2, 0, 0, 0],
...     antes=0, raise_sizes='pot', num_raises=float('inf'),
...     num_suits=4, num_ranks=13, num_hole_cards=4,
...     mandatory_num_hole_cards=2, start_stack=200
... )
>>> Dealer( # 1-2 Heads Up No Limit Short Deck
...     num_players=2, num_streets=4, blinds=[1, 2], antes=0,
...     raise_sizes=float('inf'), num_raises=float('inf'),
...     num_suits=4, num_ranks=9, num_hole_cards=2,
...     mandatory_num_hole_cards=0, start_stack=200,
...     order=[
...         'sf', 'fk', 'fl', 'fh', 'st',
...         'tk', 'tp', 'pa', 'hc'
...         ]
... )
render(mode: str = 'human', sleep: float = 0, **kwargs)[source]

Renders poker table. Render mode options are: ascii, human

Parameters

mode (str, optional) – toggle for using different renderer, by default ‘human’

reset(reset_button: bool = False, reset_stacks: bool = False)Dict[source]

Resets the table. Shuffles the deck, deals new hole cards to all players, moves the button and collects blinds and antes.

Parameters
  • reset_button (bool, optional) – reset button to first position at table, by default False

  • reset_stacks (bool, optional) – reset stack sizes to starting stack size, by default False

Returns

observation dictionary

Return type

Dict

Examples

>>> dealer = Dealer(**configs.LEDUC_TWO_PLAYER)
>>> dealer.reset()
... {'action': 1,
...  'active': [True, True],
...  'button': 1,
...  'call': 0,
...  'community_cards': [],
...  'hole_cards': [[Card (139879188163600): A♥], [Card (139879188163504): A♠]],
...  'max_raise': 2,
...  'min_raise': 2,
...  'pot': 2,
...  'stacks': [9, 9],
...  'street_commits': [0, 0]}
step(bet: float)Tuple[Dict, List[int], List[int]][source]

Advances poker game to next player. If the bet is 0, it is either considered a check or fold, depending on the previous action. The given bet is always rounded to the closest valid bet size. When it is the same distance from two valid bet sizes the smaller bet size is used, e.g. if the min raise is 10 and the bet is 5, it is rounded down to 0.

Parameters

bet (int) – number of chips bet by player currently active

Returns

observation dictionary, payouts for every player, boolean value for every player showing if that player is still active in the round

Return type

Tuple[Dict, List[int], List[int]]

Examples

>>> dealer = Dealer(**configs.LEDUC_TWO_PLAYER)
>>> obs = dealer.reset()
>>> dealer.step(0)
... ({'action': 0,
...  'active': [True, True],
...  'button': 1,
...  'call': 0,
...  'community_cards': [],
...  'hole_cards': [[Card (139879188163600): A♥], [Card (139879188163504): A♠]],
...  'max_raise': 2,
...  'min_raise': 2,
...  'pot': 2,
...  'stacks': [9, 9],
...  'street_commits': [0, 0]},
...  [0, 0],
...  [False, False])
win_probabilities(n: int = 10000)List[float][source]

Computes win probabilities for each player. If the possible remaining community card combinations are below 1000, the combinations are exhaustively checked, otherwise, n random samples are taken and averaged to compute an estimate of the win probabilities.

Parameters

n (int, optional) – max number of iterations to approximate win probabilities, by default 10000

Returns

win probabilities

Return type

List[float]

clubs.poker.evaluator module

Classes and functions to evaluate poker hands

class clubs.poker.evaluator.Evaluator(suits: int, ranks: int, cards_for_hand: int, mandatory_hole_cards: int = 0, low_end_straight: bool = True, order: Optional[list] = None)[source]

Bases: object

Evalutes poker hands using hole and community cards

Parameters
  • suits (int) – number of suits in deck

  • ranks (int) – number of ranks in deck

  • cards_for_hand (int) – number of cards used for valid poker hand

  • mandatory_hole_cards (int, optional) – number of hole cards which must be used for a hands, by default 0

  • low_end_straight (bool, optional) – toggle to include the low ace straight within valid hands, by default True

  • order (list, optional) – optional custom order of hand ranks, must be permutation of [‘sf’, ‘fk’, ‘fh’, ‘fl’, ‘st’, ‘tk’, ‘tp’, ‘pa’, ‘hc’]. if order=None, hands are ranked by rarity. by default None

evaluate(hole_cards: List[clubs.poker.card.Card], community_cards: List[clubs.poker.card.Card])int[source]

Evaluates the hand rank of a poker hand from a list of hole and a list of community cards. Empty hole and community cards are supported as well as requiring a minimum number of hole cards to be used.

Parameters
  • hole_cards (List[card.Card]) – list of hole cards

  • community_cards (List[card.Card]) – list of community cards

Returns

hand rank

Return type

int

get_rank_class(hand_rank: int)str[source]

Outputs hand rank string from integer hand rank

Parameters

hand_rank (int) – hand_rank (int): integer hand rank

Returns

hand rank string

Return type

str

speed_test(n: int = 100000)float[source]

Tests speed of evaluator

Parameters

n (int, optional) – number of iterations/hands to test, by default 100000

Returns

average time per hand evaluation

Return type

float

class clubs.poker.evaluator.LookupTable(suits: int, ranks: int, cards_for_hand: int, low_end_straight: bool = True, order: Optional[List[str]] = None)[source]

Bases: object

Lookup table maps unique prime product of hands to unique integer hand rank. The lower the rank the better the hand

Parameters
  • suits (int) – number of suits in deck

  • ranks (int) – number of ranks in deck

  • cards_for_hand (int) – number of cards used for a poker hand

  • low_end_straight (bool, optional) – toggle to include straights where ace is the lowest card, by default True

  • order (List[str], optional) – custom hand rank order, if None hands are ranked by rarity, by default None

ORDER_STRINGS = ['sf', 'fk', 'fh', 'fl', 'st', 'tk', 'tp', 'pa', 'hc']
lookup(cards: List[clubs.poker.card.Card])int[source]

Return unique hand rank for list of cards

Parameters

cards (List[card.Card]) – list of cards to be evaluated

Returns

hand rank

Return type

int

Module contents

class clubs.poker.Card(string: str)[source]

Bases: object

Cards are represented as 32-bit integers. Most of the bits are used and have a specific meaning.

bitrank

suit

rank

prime

xxxbbbbbbbbbbbbb

cdhs

rrrr

xxpppppp

  1. p = prime number of rank (deuce=2,trey=3,four=5,…,ace=41)

  2. r = rank of card (deuce=0,trey=1,four=2,five=3,…,ace=12)

  3. cdhs = suit of card (bit turned on based on suit of card)

  4. b = bit turned on depending on rank of card

  5. x = unused

Parameters

string (str) – card string of format ‘{rank}{suit}’ where rank is from [2-9, T/t, J/j, Q/q, K/k, A/a] and suit is from [S/s, H/h, D/d, C/c]

Examples

>>> card = Card('TC')
>>> card = Card('7H')
>>> card = Card('ad')
class clubs.poker.Dealer(num_players: int, num_streets: int, blinds: Union[int, List[int]], antes: Union[int, List[int]], raise_sizes: Union[float, str, List[Union[float, str]]], num_raises: Union[float, List[float]], num_suits: int, num_ranks: int, num_hole_cards: int, num_community_cards: Union[int, List[int]], num_cards_for_hand: int, mandatory_num_hole_cards: int, start_stack: int, low_end_straight: bool = True, order: Optional[List[str]] = None)[source]

Bases: object

Runs a range of different of poker games dependent on the given configuration. Supports limit, no limit and pot limit bet sizing, arbitrary deck sizes, arbitrary hole and community cards and many other options.

Parameters
  • num_players (int) – maximum number of players

  • num_streets (int) – number of streets including preflop, e.g. for texas hold’em num_streets=4

  • blinds (Union[int, List[int]]) – blind distribution as a list of ints, one for each player starting from the button e.g. [0, 1, 2] for a three player game with a sb of 1 and bb of 2, passed ints will be expanded to all players i.e. pass blinds=0 for no blinds

  • antes (Union[int, List[int]]) – ante distribution as a list of ints, one for each player starting from the button e.g. [0, 0, 5] for a three player game with a bb ante of 5, passed ints will be expanded to all players i.e. pass antes=0 for no antes

  • raise_sizes (Union[float, str, List[Union[float, str]]]) – max raise sizes for each street, valid raise sizes are ints, floats, and ‘pot’, e.g. for a 1-2 limit hold’em the raise sizes should be [2, 2, 4, 4] as the small and big bet are 2 and 4. float(‘inf’) can be used for no limit games. pot limit raise sizes can be set using ‘pot’. if only a single int, float or string is passed the value is expanded to a list the length of number of streets, e.g. for a standard no limit game pass raise_sizes=float(‘inf’)

  • num_raises (Union[float, List[float]]) – max number of bets for each street including preflop, valid raise numbers are ints and floats. if only a single int or float is passed the value is expanded to a list the length of number of streets, e.g. for a standard limit game pass num_raises=4

  • num_suits (int) – number of suits to use in deck, must be between 1 and 4

  • num_ranks (int) – number of ranks to use in deck, must be between 1 and 13

  • num_hole_cards (int) – number of hole cards per player, must be greater than 0

  • num_community_cards (Union[int, List[int]]) – number of community cards per street including preflop, e.g. for texas hold’em pass num_community_cards=[0, 3, 1, 1]. if only a single int is passed, it is expanded to a list the length of number of streets

  • num_cards_for_hand (int) – number of cards for a valid poker hand, e.g. for texas hold’em num_cards_for_hand=5

  • mandatory_num_hole_cards (int) – number of hole cards which have to be used for the hand, e.g. for pot limit omaha mandatory_num_hole_cards=2

  • start_stack (int) – number of chips each player starts with

  • low_end_straight (bool, optional) – toggle to include the low ace straight within valid hands, by default True

  • order (Optional[List[str]], optional) – optional custom order of hand ranks, must be permutation of [‘sf’, ‘fk’, ‘fh’, ‘fl’, ‘st’, ‘tk’, ‘tp’, ‘pa’, ‘hc’]. if order=None, hands are ranked by rarity. by default None

Examples

>>> Dealer( # 1-2 Heads Up No Limit Texas Hold'em
...     num_players=2, num_streets=4, blinds=[1, 2], antes=0,
...     raise_sizes=float('inf'), num_raises=float('inf'),
...     num_suits=4, num_ranks=13, num_hole_cards=2,
...     mandatory_num_hole_cards=0, start_stack=200
... )
>>> Dealer( # 1-2 6 Player PLO
...     num_players=6, num_streets=4, blinds=[0, 1, 2, 0, 0, 0],
...     antes=0, raise_sizes='pot', num_raises=float('inf'),
...     num_suits=4, num_ranks=13, num_hole_cards=4,
...     mandatory_num_hole_cards=2, start_stack=200
... )
>>> Dealer( # 1-2 Heads Up No Limit Short Deck
...     num_players=2, num_streets=4, blinds=[1, 2], antes=0,
...     raise_sizes=float('inf'), num_raises=float('inf'),
...     num_suits=4, num_ranks=9, num_hole_cards=2,
...     mandatory_num_hole_cards=0, start_stack=200,
...     order=[
...         'sf', 'fk', 'fl', 'fh', 'st',
...         'tk', 'tp', 'pa', 'hc'
...         ]
... )
render(mode: str = 'human', sleep: float = 0, **kwargs)[source]

Renders poker table. Render mode options are: ascii, human

Parameters

mode (str, optional) – toggle for using different renderer, by default ‘human’

reset(reset_button: bool = False, reset_stacks: bool = False)Dict[source]

Resets the table. Shuffles the deck, deals new hole cards to all players, moves the button and collects blinds and antes.

Parameters
  • reset_button (bool, optional) – reset button to first position at table, by default False

  • reset_stacks (bool, optional) – reset stack sizes to starting stack size, by default False

Returns

observation dictionary

Return type

Dict

Examples

>>> dealer = Dealer(**configs.LEDUC_TWO_PLAYER)
>>> dealer.reset()
... {'action': 1,
...  'active': [True, True],
...  'button': 1,
...  'call': 0,
...  'community_cards': [],
...  'hole_cards': [[Card (139879188163600): A♥], [Card (139879188163504): A♠]],
...  'max_raise': 2,
...  'min_raise': 2,
...  'pot': 2,
...  'stacks': [9, 9],
...  'street_commits': [0, 0]}
step(bet: float)Tuple[Dict, List[int], List[int]][source]

Advances poker game to next player. If the bet is 0, it is either considered a check or fold, depending on the previous action. The given bet is always rounded to the closest valid bet size. When it is the same distance from two valid bet sizes the smaller bet size is used, e.g. if the min raise is 10 and the bet is 5, it is rounded down to 0.

Parameters

bet (int) – number of chips bet by player currently active

Returns

observation dictionary, payouts for every player, boolean value for every player showing if that player is still active in the round

Return type

Tuple[Dict, List[int], List[int]]

Examples

>>> dealer = Dealer(**configs.LEDUC_TWO_PLAYER)
>>> obs = dealer.reset()
>>> dealer.step(0)
... ({'action': 0,
...  'active': [True, True],
...  'button': 1,
...  'call': 0,
...  'community_cards': [],
...  'hole_cards': [[Card (139879188163600): A♥], [Card (139879188163504): A♠]],
...  'max_raise': 2,
...  'min_raise': 2,
...  'pot': 2,
...  'stacks': [9, 9],
...  'street_commits': [0, 0]},
...  [0, 0],
...  [False, False])
win_probabilities(n: int = 10000)List[float][source]

Computes win probabilities for each player. If the possible remaining community card combinations are below 1000, the combinations are exhaustively checked, otherwise, n random samples are taken and averaged to compute an estimate of the win probabilities.

Parameters

n (int, optional) – max number of iterations to approximate win probabilities, by default 10000

Returns

win probabilities

Return type

List[float]

class clubs.poker.Deck(num_suits: int, num_ranks: int)[source]

Bases: object

A deck contains at most 52 cards, 13 ranks 4 suits. Any “subdeck” of the standard 52 card deck is valid, i.e. the number of suits must be between 1 and 4 and number of ranks between 1 and 13. A deck can be tricked to ensure a certain order of cards.

Parameters
  • num_suits (int) – number of suits to use in deck

  • num_ranks (int) – number of ranks to use in deck

draw(n: int = 1)List[clubs.poker.card.Card][source]

Draws cards from the top of the deck. If the number of cards to draw exceeds the number of cards in the deck, all cards left in the deck are returned.

Parameters

n (int, optional) – number of cards to draw, by default 1

Returns

cards drawn from the deck

Return type

List[Card]

shuffle()clubs.poker.card.Deck[source]

Shuffles the deck. If a tricking order is given, the desired cards are placed on the top of the deck after shuffling.

Returns

self

Return type

Deck

trick(top_cards: List[clubs.poker.card.Card])clubs.poker.card.Deck[source]

Tricks the deck by placing a fixed order of cards on the top of the deck and shuffling the rest. E.g. deck.trick([Card(‘AS’), Card(‘2H’)]) places the ace of spades and deuce of hearts on the top of the deck.

Parameters

top_cards (Optional[List[Union[str, Card]]], optional) – list of cards to be placed on the top of the deck, by default None, by default None

Returns

self

Return type

Deck

untrick()clubs.poker.card.Deck[source]

Removes the tricked cards from the top of the deck.

Returns

self

Return type

Deck

class clubs.poker.Evaluator(suits: int, ranks: int, cards_for_hand: int, mandatory_hole_cards: int = 0, low_end_straight: bool = True, order: Optional[list] = None)[source]

Bases: object

Evalutes poker hands using hole and community cards

Parameters
  • suits (int) – number of suits in deck

  • ranks (int) – number of ranks in deck

  • cards_for_hand (int) – number of cards used for valid poker hand

  • mandatory_hole_cards (int, optional) – number of hole cards which must be used for a hands, by default 0

  • low_end_straight (bool, optional) – toggle to include the low ace straight within valid hands, by default True

  • order (list, optional) – optional custom order of hand ranks, must be permutation of [‘sf’, ‘fk’, ‘fh’, ‘fl’, ‘st’, ‘tk’, ‘tp’, ‘pa’, ‘hc’]. if order=None, hands are ranked by rarity. by default None

evaluate(hole_cards: List[clubs.poker.card.Card], community_cards: List[clubs.poker.card.Card])int[source]

Evaluates the hand rank of a poker hand from a list of hole and a list of community cards. Empty hole and community cards are supported as well as requiring a minimum number of hole cards to be used.

Parameters
  • hole_cards (List[card.Card]) – list of hole cards

  • community_cards (List[card.Card]) – list of community cards

Returns

hand rank

Return type

int

get_rank_class(hand_rank: int)str[source]

Outputs hand rank string from integer hand rank

Parameters

hand_rank (int) – hand_rank (int): integer hand rank

Returns

hand rank string

Return type

str

speed_test(n: int = 100000)float[source]

Tests speed of evaluator

Parameters

n (int, optional) – number of iterations/hands to test, by default 100000

Returns

average time per hand evaluation

Return type

float

class clubs.poker.LookupTable(suits: int, ranks: int, cards_for_hand: int, low_end_straight: bool = True, order: Optional[List[str]] = None)[source]

Bases: object

Lookup table maps unique prime product of hands to unique integer hand rank. The lower the rank the better the hand

Parameters
  • suits (int) – number of suits in deck

  • ranks (int) – number of ranks in deck

  • cards_for_hand (int) – number of cards used for a poker hand

  • low_end_straight (bool, optional) – toggle to include straights where ace is the lowest card, by default True

  • order (List[str], optional) – custom hand rank order, if None hands are ranked by rarity, by default None

ORDER_STRINGS = ['sf', 'fk', 'fh', 'fl', 'st', 'tk', 'tp', 'pa', 'hc']
lookup(cards: List[clubs.poker.card.Card])int[source]

Return unique hand rank for list of cards

Parameters

cards (List[card.Card]) – list of cards to be evaluated

Returns

hand rank

Return type

int