Create Game History for an LLM#
If you plan to register LLMs as players, you might want to pass the full game history. This way, the LLM can recognize behavioral patterns of players and make better decisions, perhaps even exploit the weaknesses of the players. In this notebook we define an EventListener class that maintains a game history that you can pass to an LLM.
from maverick.players import FoldBot, CallBot, AggressiveBot
from maverick import (
PlayerLike,
PlayerState,
Game,
GameEvent,
GameEventType,
PlayerAction,
ActionType,
)
class EventListener:
def __init__(self, game: Game=None):
self.game = game
self.events = []
self.id_to_player = {}
self.max_line_length = 80
self.dump = []
self.listen(game)
def listen(self, game: Game=None) -> None:
if game is None:
return
self.game = game
self._subscribe_to_events()
self._register_players()
def _subscribe_to_events(self) -> None:
for event_type in GameEventType:
self.game.subscribe(event_type, self._handle_event)
def _register_players(self) -> None:
self.id_to_player = {player.id: player for player in self.game.state.players}
@property
def history(self) -> str:
return "\n".join(self.events)
def _log_betting_round_started(self) -> None:
if len(self.game.state.community_cards) == 0:
self.events.append("Community cards: None")
else:
self.events.append(f"Community cards: {[card.code() for card in self.game.state.community_cards]}")
current_bet = self.game.state.current_bet
current_pot = self.game.state.pot
last_raise_size = self.game.state.last_raise_size
self.events.append((
f"Current pot size: {current_pot}. "
f"Current bet: {current_bet}. "
f"Minimum raise size: {last_raise_size}."
))
self.events.append("")
def _log_section_header(self, title: str, chr:str, *, add_empty_line:bool=True) -> None:
len_title = len(title) + 2 if len(title) > 0 else 0
len_prefix_suffix = (self.max_line_length - len_title) // 2
title = f" {title} " if len_title > 0 else ""
msg = chr * len_prefix_suffix + f"{title}" + chr * len_prefix_suffix
if len(msg) < self.max_line_length:
msg += chr
elif len(msg) > self.max_line_length:
msg = msg[:self.max_line_length]
msg = msg[:self.max_line_length]
self.events.append(msg)
if add_empty_line:
self.events.append("")
def _handle_event(self, event: GameEvent, game: Game) -> None:
"""Count each type of event."""
self.dump.append(event.model_dump(mode="json"))
hand_number = game.state.hand_number
match event.type:
case GameEventType.GAME_STARTED:
self._log_section_header("", "=", add_empty_line=False)
self._log_section_header(f"Game Started", "=", add_empty_line=False)
self._log_section_header("", "=")
self.events.append("Game type: No-Limit Texas Hold'em")
self.events.append(f"Small blind: {game.state.small_blind}")
self.events.append(f"Big blind: {game.state.big_blind}")
self.events.append(f"Ante: {game.state.ante}")
self.events.append("")
self.events.append("Players at the table:")
for player in self.game.state.players:
self.events.append(f" {player.name}: Starting stack {player.state.stack}")
self.events.append("")
case GameEventType.HAND_STARTED:
if len(self.events) > 0 and len(self.events[-1].strip()) > 0:
self.events.append("")
self._log_section_header(f"Hand {hand_number}", "=")
button_player = game.button
self.events.append(f"{button_player.name} is on the button.")
small_blind_player = game.small_blind
self.events.append(f"{small_blind_player.name} is the small blind.")
big_blind_player = game.big_blind
self.events.append(f"{big_blind_player.name} is the big blind.")
utg_position = game.table.next_occupied_seat(big_blind_player.state.seat, active=True)
utg_player = game.table[utg_position]
self.events.append(f"{utg_player.name} is under the gun.")
self.events.append("")
self.events.append(f"Player stacks at the beginning of hand {hand_number}:")
for player in game.state.players:
self.events.append(f" {player.name}: {player.state.stack}")
self.events.append("")
case GameEventType.BETTING_ROUND_STARTED:
street_name = game.state.street.name
self._log_section_header(f"Hand: {hand_number} | Street: {street_name}", "-")
self._log_betting_round_started()
case GameEventType.PLAYER_ACTION_TAKEN:
action: PlayerAction = event.action
player_id = event.player_id
player = self.id_to_player[player_id]
current_bet = game.state.current_bet
current_pot = game.state.pot
last_raise_size = game.state.last_raise_size
match action.action_type:
case ActionType.FOLD:
self.events.append(f"[{player.name}] folds. Remaining stack: {player.state.stack}.")
case ActionType.CALL:
self.events.append(f"[{player.name}] calls. Remaining stack: {player.state.stack}.")
case ActionType.RAISE:
self.events.append(f"[{player.name}] raises bet to {current_bet}. Remaining stack: {player.state.stack}.")
case ActionType.CHECK:
self.events.append(f"[{player.name}] checks. Remaining stack: {player.state.stack}.")
case ActionType.BET:
self.events.append(f"[{player.name}] bets {action.amount}. Remaining stack: {player.state.stack}.")
self.events.append((
f"Current pot size: {current_pot}. "
f"Current bet: {current_bet}. "
f"Minimum raise size: {last_raise_size}."
))
case GameEventType.BETTING_ROUND_COMPLETED:
self.events.append("")
self.events.append(f"Player standings after the betting round:")
for player in game.state.players:
player_pot = player.state.total_contributed
state_type = player.state.state_type.name
self.events.append(f" {player.name}: State={state_type}, Pot={player_pot}, Stack={player.state.stack}")
self.events.append("")
case GameEventType.SHOWDOWN_STARTED:
self._log_section_header(f"Hand: {hand_number} | SHOWDOWN", "-")
case GameEventType.PLAYER_CARDS_REVEALED:
player_id = event.player_id
player = self.id_to_player[player_id]
payload = event.payload
self.events.append((
f"{player.name} reveals: {payload['holding']}. "
f"Best hand: {payload['best_hand']} ({payload['best_hand_type']}). "
f"Hand score: {payload['best_score']}."
))
case GameEventType.SHOWDOWN_COMPLETED:
self.events.append("")
self.events.append(f"Player stacks after showdown:")
for player in game.state.players:
self.events.append(f" {player.name}: {player.state.stack}")
self.events.append("")
case GameEventType.POT_WON:
player_id = event.player_id
player = self.id_to_player[player_id]
amount = event.payload.get("amount", 0)
self.events.append(f"{player.name} wins {amount}.")
case GameEventType.PLAYER_ELIMINATED:
player_id = event.player_id
player = self.id_to_player[player_id]
self.events.append(f"{player.name} has been eliminated from the game.")
case GameEventType.HAND_ENDED:
pass
game = Game(small_blind=10, big_blind=20, max_hands=10)
players: list[PlayerLike] = [
CallBot(name="CallBot", state=PlayerState(stack=1000)),
AggressiveBot(name="AggroBot", state=PlayerState(stack=1000)),
FoldBot(name="FoldBot", state=PlayerState(stack=1000)),
]
for player in players:
game.add_player(player)
event_listener = EventListener(game)
game.start()
You can turn the list of events that happened during the game as a Pandas DataFrame:
print(event_listener.history)
================================================================================
================================= Game Started =================================
================================================================================
Game type: No-Limit Texas Hold'em
Small blind: 10
Big blind: 20
Ante: 0
Players at the table:
CallBot: Starting stack 1000
AggroBot: Starting stack 1000
FoldBot: Starting stack 1000
==================================== Hand 1 ====================================
CallBot is on the button.
AggroBot is the small blind.
FoldBot is the big blind.
CallBot is under the gun.
Player stacks at the beginning of hand 1:
CallBot: 1000
AggroBot: 1000
FoldBot: 1000
-------------------------- Hand: 1 | Street: PRE_FLOP --------------------------
Community cards: None
Current pot size: 30. Current bet: 20. Minimum raise size: 20.
[CallBot] calls. Remaining stack: 980.
Current pot size: 50. Current bet: 20. Minimum raise size: 20.
[AggroBot] raises bet to 40. Remaining stack: 960.
Current pot size: 80. Current bet: 40. Minimum raise size: 20.
[FoldBot] folds. Remaining stack: 980.
Current pot size: 80. Current bet: 40. Minimum raise size: 20.
[CallBot] calls. Remaining stack: 960.
Current pot size: 100. Current bet: 40. Minimum raise size: 20.
Player standings after the betting round:
CallBot: State=ACTIVE, Pot=40, Stack=960
AggroBot: State=ACTIVE, Pot=40, Stack=960
FoldBot: State=FOLDED, Pot=20, Stack=980
---------------------------- Hand: 1 | Street: FLOP ----------------------------
Community cards: ['Ts', 'Td', '2c']
Current pot size: 100. Current bet: 0. Minimum raise size: 0.
[AggroBot] bets 40. Remaining stack: 920.
Current pot size: 140. Current bet: 40. Minimum raise size: 40.
[CallBot] calls. Remaining stack: 920.
Current pot size: 180. Current bet: 40. Minimum raise size: 40.
Player standings after the betting round:
CallBot: State=ACTIVE, Pot=80, Stack=920
AggroBot: State=ACTIVE, Pot=80, Stack=920
FoldBot: State=FOLDED, Pot=20, Stack=980
---------------------------- Hand: 1 | Street: TURN ----------------------------
Community cards: ['Ts', 'Td', '2c', '6d']
Current pot size: 180. Current bet: 0. Minimum raise size: 0.
[AggroBot] bets 40. Remaining stack: 880.
Current pot size: 220. Current bet: 40. Minimum raise size: 40.
[CallBot] calls. Remaining stack: 880.
Current pot size: 260. Current bet: 40. Minimum raise size: 40.
Player standings after the betting round:
CallBot: State=ACTIVE, Pot=120, Stack=880
AggroBot: State=ACTIVE, Pot=120, Stack=880
FoldBot: State=FOLDED, Pot=20, Stack=980
--------------------------- Hand: 1 | Street: RIVER ----------------------------
Community cards: ['Ts', 'Td', '2c', '6d', '9h']
Current pot size: 260. Current bet: 0. Minimum raise size: 0.
[AggroBot] bets 40. Remaining stack: 840.
Current pot size: 300. Current bet: 40. Minimum raise size: 40.
[CallBot] calls. Remaining stack: 840.
Current pot size: 340. Current bet: 40. Minimum raise size: 40.
Player standings after the betting round:
CallBot: State=ACTIVE, Pot=160, Stack=840
AggroBot: State=ACTIVE, Pot=160, Stack=840
FoldBot: State=FOLDED, Pot=20, Stack=980
------------------------------ Hand: 1 | SHOWDOWN ------------------------------
CallBot reveals: ['8d', 'Ah']. Best hand: ['8d', 'Ah', 'Ts', 'Td', '9h'] (PAIR). Hand score: 210.140908.
AggroBot reveals: ['8h', 'Jh']. Best hand: ['8h', 'Jh', 'Ts', 'Td', '9h'] (PAIR). Hand score: 210.110908.
CallBot wins 340.
Player stacks after showdown:
CallBot: 1180
AggroBot: 840
FoldBot: 980
==================================== Hand 2 ====================================
AggroBot is on the button.
FoldBot is the small blind.
CallBot is the big blind.
AggroBot is under the gun.
Player stacks at the beginning of hand 2:
CallBot: 1180
AggroBot: 840
FoldBot: 980
-------------------------- Hand: 2 | Street: PRE_FLOP --------------------------
Community cards: None
Current pot size: 30. Current bet: 20. Minimum raise size: 20.
[AggroBot] raises bet to 40. Remaining stack: 800.
Current pot size: 70. Current bet: 40. Minimum raise size: 20.
[FoldBot] folds. Remaining stack: 970.
Current pot size: 70. Current bet: 40. Minimum raise size: 20.
[CallBot] calls. Remaining stack: 1140.
Current pot size: 90. Current bet: 40. Minimum raise size: 20.
Player standings after the betting round:
CallBot: State=ACTIVE, Pot=40, Stack=1140
AggroBot: State=ACTIVE, Pot=40, Stack=800
FoldBot: State=FOLDED, Pot=10, Stack=970
---------------------------- Hand: 2 | Street: FLOP ----------------------------
Community cards: ['2s', '8s', 'Ts']
Current pot size: 90. Current bet: 0. Minimum raise size: 0.
[CallBot] checks. Remaining stack: 1140.
Current pot size: 90. Current bet: 0. Minimum raise size: 0.
[AggroBot] bets 40. Remaining stack: 760.
Current pot size: 130. Current bet: 40. Minimum raise size: 40.
[CallBot] calls. Remaining stack: 1100.
Current pot size: 170. Current bet: 40. Minimum raise size: 40.
Player standings after the betting round:
CallBot: State=ACTIVE, Pot=80, Stack=1100
AggroBot: State=ACTIVE, Pot=80, Stack=760
FoldBot: State=FOLDED, Pot=10, Stack=970
---------------------------- Hand: 2 | Street: TURN ----------------------------
Community cards: ['2s', '8s', 'Ts', '3h']
Current pot size: 170. Current bet: 0. Minimum raise size: 0.
[CallBot] checks. Remaining stack: 1100.
Current pot size: 170. Current bet: 0. Minimum raise size: 0.
[AggroBot] bets 40. Remaining stack: 720.
Current pot size: 210. Current bet: 40. Minimum raise size: 40.
[CallBot] calls. Remaining stack: 1060.
Current pot size: 250. Current bet: 40. Minimum raise size: 40.
Player standings after the betting round:
CallBot: State=ACTIVE, Pot=120, Stack=1060
AggroBot: State=ACTIVE, Pot=120, Stack=720
FoldBot: State=FOLDED, Pot=10, Stack=970
--------------------------- Hand: 2 | Street: RIVER ----------------------------
Community cards: ['2s', '8s', 'Ts', '3h', '2c']
Current pot size: 250. Current bet: 0. Minimum raise size: 0.
[CallBot] checks. Remaining stack: 1060.
Current pot size: 250. Current bet: 0. Minimum raise size: 0.
[AggroBot] bets 40. Remaining stack: 680.
Current pot size: 290. Current bet: 40. Minimum raise size: 40.
[CallBot] calls. Remaining stack: 1020.
Current pot size: 330. Current bet: 40. Minimum raise size: 40.
Player standings after the betting round:
CallBot: State=ACTIVE, Pot=160, Stack=1020
AggroBot: State=ACTIVE, Pot=160, Stack=680
FoldBot: State=FOLDED, Pot=10, Stack=970
------------------------------ Hand: 2 | SHOWDOWN ------------------------------
CallBot reveals: ['Js', '7c']. Best hand: ['Js', '2s', '8s', 'Ts', '2c'] (PAIR). Hand score: 202.111008.
AggroBot reveals: ['Td', '2h']. Best hand: ['Td', '2h', '2s', 'Ts', '2c'] (FULL_HOUSE). Hand score: 702.1.
AggroBot wins 330.
Player stacks after showdown:
CallBot: 1020
AggroBot: 1010
FoldBot: 970
==================================== Hand 3 ====================================
FoldBot is on the button.
CallBot is the small blind.
AggroBot is the big blind.
FoldBot is under the gun.
Player stacks at the beginning of hand 3:
CallBot: 1020
AggroBot: 1010
FoldBot: 970
-------------------------- Hand: 3 | Street: PRE_FLOP --------------------------
Community cards: None
Current pot size: 30. Current bet: 20. Minimum raise size: 20.
[FoldBot] folds. Remaining stack: 970.
Current pot size: 30. Current bet: 20. Minimum raise size: 20.
[CallBot] calls. Remaining stack: 1000.
Current pot size: 40. Current bet: 20. Minimum raise size: 20.
[AggroBot] raises bet to 40. Remaining stack: 970.
Current pot size: 60. Current bet: 40. Minimum raise size: 20.
[CallBot] calls. Remaining stack: 980.
Current pot size: 80. Current bet: 40. Minimum raise size: 20.
Player standings after the betting round:
CallBot: State=ACTIVE, Pot=40, Stack=980
AggroBot: State=ACTIVE, Pot=40, Stack=970
FoldBot: State=FOLDED, Pot=0, Stack=970
---------------------------- Hand: 3 | Street: FLOP ----------------------------
Community cards: ['2d', 'Ts', 'Tc']
Current pot size: 80. Current bet: 0. Minimum raise size: 0.
[CallBot] checks. Remaining stack: 980.
Current pot size: 80. Current bet: 0. Minimum raise size: 0.
[AggroBot] bets 40. Remaining stack: 930.
Current pot size: 120. Current bet: 40. Minimum raise size: 40.
[CallBot] calls. Remaining stack: 940.
Current pot size: 160. Current bet: 40. Minimum raise size: 40.
Player standings after the betting round:
CallBot: State=ACTIVE, Pot=80, Stack=940
AggroBot: State=ACTIVE, Pot=80, Stack=930
FoldBot: State=FOLDED, Pot=0, Stack=970
---------------------------- Hand: 3 | Street: TURN ----------------------------
Community cards: ['2d', 'Ts', 'Tc', 'Td']
Current pot size: 160. Current bet: 0. Minimum raise size: 0.
[CallBot] checks. Remaining stack: 940.
Current pot size: 160. Current bet: 0. Minimum raise size: 0.
[AggroBot] bets 40. Remaining stack: 890.
Current pot size: 200. Current bet: 40. Minimum raise size: 40.
[CallBot] calls. Remaining stack: 900.
Current pot size: 240. Current bet: 40. Minimum raise size: 40.
Player standings after the betting round:
CallBot: State=ACTIVE, Pot=120, Stack=900
AggroBot: State=ACTIVE, Pot=120, Stack=890
FoldBot: State=FOLDED, Pot=0, Stack=970
--------------------------- Hand: 3 | Street: RIVER ----------------------------
Community cards: ['2d', 'Ts', 'Tc', 'Td', '8s']
Current pot size: 240. Current bet: 0. Minimum raise size: 0.
[CallBot] checks. Remaining stack: 900.
Current pot size: 240. Current bet: 0. Minimum raise size: 0.
[AggroBot] bets 40. Remaining stack: 850.
Current pot size: 280. Current bet: 40. Minimum raise size: 40.
[CallBot] calls. Remaining stack: 860.
Current pot size: 320. Current bet: 40. Minimum raise size: 40.
Player standings after the betting round:
CallBot: State=ACTIVE, Pot=160, Stack=860
AggroBot: State=ACTIVE, Pot=160, Stack=850
FoldBot: State=FOLDED, Pot=0, Stack=970
------------------------------ Hand: 3 | SHOWDOWN ------------------------------
CallBot reveals: ['3h', 'Js']. Best hand: ['Js', 'Ts', 'Tc', 'Td', '8s'] (THREE_OF_A_KIND). Hand score: 410.1108.
AggroBot reveals: ['9d', '4h']. Best hand: ['9d', 'Ts', 'Tc', 'Td', '8s'] (THREE_OF_A_KIND). Hand score: 410.0908.
CallBot wins 320.
Player stacks after showdown:
CallBot: 1180
AggroBot: 850
FoldBot: 970
==================================== Hand 4 ====================================
CallBot is on the button.
AggroBot is the small blind.
FoldBot is the big blind.
CallBot is under the gun.
Player stacks at the beginning of hand 4:
CallBot: 1180
AggroBot: 850
FoldBot: 970
-------------------------- Hand: 4 | Street: PRE_FLOP --------------------------
Community cards: None
Current pot size: 30. Current bet: 20. Minimum raise size: 20.
[CallBot] calls. Remaining stack: 1160.
Current pot size: 50. Current bet: 20. Minimum raise size: 20.
[AggroBot] raises bet to 40. Remaining stack: 810.
Current pot size: 80. Current bet: 40. Minimum raise size: 20.
[FoldBot] folds. Remaining stack: 950.
Current pot size: 80. Current bet: 40. Minimum raise size: 20.
[CallBot] calls. Remaining stack: 1140.
Current pot size: 100. Current bet: 40. Minimum raise size: 20.
Player standings after the betting round:
CallBot: State=ACTIVE, Pot=40, Stack=1140
AggroBot: State=ACTIVE, Pot=40, Stack=810
FoldBot: State=FOLDED, Pot=20, Stack=950
---------------------------- Hand: 4 | Street: FLOP ----------------------------
Community cards: ['9h', '6c', 'Ad']
Current pot size: 100. Current bet: 0. Minimum raise size: 0.
[AggroBot] bets 40. Remaining stack: 770.
Current pot size: 140. Current bet: 40. Minimum raise size: 40.
[CallBot] calls. Remaining stack: 1100.
Current pot size: 180. Current bet: 40. Minimum raise size: 40.
Player standings after the betting round:
CallBot: State=ACTIVE, Pot=80, Stack=1100
AggroBot: State=ACTIVE, Pot=80, Stack=770
FoldBot: State=FOLDED, Pot=20, Stack=950
---------------------------- Hand: 4 | Street: TURN ----------------------------
Community cards: ['9h', '6c', 'Ad', '5h']
Current pot size: 180. Current bet: 0. Minimum raise size: 0.
[AggroBot] bets 40. Remaining stack: 730.
Current pot size: 220. Current bet: 40. Minimum raise size: 40.
[CallBot] calls. Remaining stack: 1060.
Current pot size: 260. Current bet: 40. Minimum raise size: 40.
Player standings after the betting round:
CallBot: State=ACTIVE, Pot=120, Stack=1060
AggroBot: State=ACTIVE, Pot=120, Stack=730
FoldBot: State=FOLDED, Pot=20, Stack=950
--------------------------- Hand: 4 | Street: RIVER ----------------------------
Community cards: ['9h', '6c', 'Ad', '5h', '8d']
Current pot size: 260. Current bet: 0. Minimum raise size: 0.
[AggroBot] bets 40. Remaining stack: 690.
Current pot size: 300. Current bet: 40. Minimum raise size: 40.
[CallBot] calls. Remaining stack: 1020.
Current pot size: 340. Current bet: 40. Minimum raise size: 40.
Player standings after the betting round:
CallBot: State=ACTIVE, Pot=160, Stack=1020
AggroBot: State=ACTIVE, Pot=160, Stack=690
FoldBot: State=FOLDED, Pot=20, Stack=950
------------------------------ Hand: 4 | SHOWDOWN ------------------------------
CallBot reveals: ['5c', 'Ah']. Best hand: ['5c', 'Ah', '9h', 'Ad', '5h'] (TWO_PAIR). Hand score: 314.0509.
AggroBot reveals: ['6h', 'Qs']. Best hand: ['6h', 'Qs', '9h', '6c', 'Ad'] (PAIR). Hand score: 206.141209.
CallBot wins 340.
Player stacks after showdown:
CallBot: 1360
AggroBot: 690
FoldBot: 950
==================================== Hand 5 ====================================
AggroBot is on the button.
FoldBot is the small blind.
CallBot is the big blind.
AggroBot is under the gun.
Player stacks at the beginning of hand 5:
CallBot: 1360
AggroBot: 690
FoldBot: 950
-------------------------- Hand: 5 | Street: PRE_FLOP --------------------------
Community cards: None
Current pot size: 30. Current bet: 20. Minimum raise size: 20.
[AggroBot] raises bet to 40. Remaining stack: 650.
Current pot size: 70. Current bet: 40. Minimum raise size: 20.
[FoldBot] folds. Remaining stack: 940.
Current pot size: 70. Current bet: 40. Minimum raise size: 20.
[CallBot] calls. Remaining stack: 1320.
Current pot size: 90. Current bet: 40. Minimum raise size: 20.
Player standings after the betting round:
CallBot: State=ACTIVE, Pot=40, Stack=1320
AggroBot: State=ACTIVE, Pot=40, Stack=650
FoldBot: State=FOLDED, Pot=10, Stack=940
---------------------------- Hand: 5 | Street: FLOP ----------------------------
Community cards: ['4s', 'Td', '7s']
Current pot size: 90. Current bet: 0. Minimum raise size: 0.
[CallBot] checks. Remaining stack: 1320.
Current pot size: 90. Current bet: 0. Minimum raise size: 0.
[AggroBot] bets 40. Remaining stack: 610.
Current pot size: 130. Current bet: 40. Minimum raise size: 40.
[CallBot] calls. Remaining stack: 1280.
Current pot size: 170. Current bet: 40. Minimum raise size: 40.
Player standings after the betting round:
CallBot: State=ACTIVE, Pot=80, Stack=1280
AggroBot: State=ACTIVE, Pot=80, Stack=610
FoldBot: State=FOLDED, Pot=10, Stack=940
---------------------------- Hand: 5 | Street: TURN ----------------------------
Community cards: ['4s', 'Td', '7s', 'Kh']
Current pot size: 170. Current bet: 0. Minimum raise size: 0.
[CallBot] checks. Remaining stack: 1280.
Current pot size: 170. Current bet: 0. Minimum raise size: 0.
[AggroBot] bets 40. Remaining stack: 570.
Current pot size: 210. Current bet: 40. Minimum raise size: 40.
[CallBot] calls. Remaining stack: 1240.
Current pot size: 250. Current bet: 40. Minimum raise size: 40.
Player standings after the betting round:
CallBot: State=ACTIVE, Pot=120, Stack=1240
AggroBot: State=ACTIVE, Pot=120, Stack=570
FoldBot: State=FOLDED, Pot=10, Stack=940
--------------------------- Hand: 5 | Street: RIVER ----------------------------
Community cards: ['4s', 'Td', '7s', 'Kh', '6d']
Current pot size: 250. Current bet: 0. Minimum raise size: 0.
[CallBot] checks. Remaining stack: 1240.
Current pot size: 250. Current bet: 0. Minimum raise size: 0.
[AggroBot] bets 40. Remaining stack: 530.
Current pot size: 290. Current bet: 40. Minimum raise size: 40.
[CallBot] calls. Remaining stack: 1200.
Current pot size: 330. Current bet: 40. Minimum raise size: 40.
Player standings after the betting round:
CallBot: State=ACTIVE, Pot=160, Stack=1200
AggroBot: State=ACTIVE, Pot=160, Stack=530
FoldBot: State=FOLDED, Pot=10, Stack=940
------------------------------ Hand: 5 | SHOWDOWN ------------------------------
CallBot reveals: ['Ah', 'As']. Best hand: ['Ah', 'As', 'Td', '7s', 'Kh'] (PAIR). Hand score: 214.131007.
AggroBot reveals: ['7c', '9s']. Best hand: ['7c', '9s', 'Td', '7s', 'Kh'] (PAIR). Hand score: 207.131009.
CallBot wins 330.
Player stacks after showdown:
CallBot: 1530
AggroBot: 530
FoldBot: 940
==================================== Hand 6 ====================================
FoldBot is on the button.
CallBot is the small blind.
AggroBot is the big blind.
FoldBot is under the gun.
Player stacks at the beginning of hand 6:
CallBot: 1530
AggroBot: 530
FoldBot: 940
-------------------------- Hand: 6 | Street: PRE_FLOP --------------------------
Community cards: None
Current pot size: 30. Current bet: 20. Minimum raise size: 20.
[FoldBot] folds. Remaining stack: 940.
Current pot size: 30. Current bet: 20. Minimum raise size: 20.
[CallBot] calls. Remaining stack: 1510.
Current pot size: 40. Current bet: 20. Minimum raise size: 20.
[AggroBot] raises bet to 40. Remaining stack: 490.
Current pot size: 60. Current bet: 40. Minimum raise size: 20.
[CallBot] calls. Remaining stack: 1490.
Current pot size: 80. Current bet: 40. Minimum raise size: 20.
Player standings after the betting round:
CallBot: State=ACTIVE, Pot=40, Stack=1490
AggroBot: State=ACTIVE, Pot=40, Stack=490
FoldBot: State=FOLDED, Pot=0, Stack=940
---------------------------- Hand: 6 | Street: FLOP ----------------------------
Community cards: ['8d', '5s', '3c']
Current pot size: 80. Current bet: 0. Minimum raise size: 0.
[CallBot] checks. Remaining stack: 1490.
Current pot size: 80. Current bet: 0. Minimum raise size: 0.
[AggroBot] bets 40. Remaining stack: 450.
Current pot size: 120. Current bet: 40. Minimum raise size: 40.
[CallBot] calls. Remaining stack: 1450.
Current pot size: 160. Current bet: 40. Minimum raise size: 40.
Player standings after the betting round:
CallBot: State=ACTIVE, Pot=80, Stack=1450
AggroBot: State=ACTIVE, Pot=80, Stack=450
FoldBot: State=FOLDED, Pot=0, Stack=940
---------------------------- Hand: 6 | Street: TURN ----------------------------
Community cards: ['8d', '5s', '3c', '3s']
Current pot size: 160. Current bet: 0. Minimum raise size: 0.
[CallBot] checks. Remaining stack: 1450.
Current pot size: 160. Current bet: 0. Minimum raise size: 0.
[AggroBot] bets 40. Remaining stack: 410.
Current pot size: 200. Current bet: 40. Minimum raise size: 40.
[CallBot] calls. Remaining stack: 1410.
Current pot size: 240. Current bet: 40. Minimum raise size: 40.
Player standings after the betting round:
CallBot: State=ACTIVE, Pot=120, Stack=1410
AggroBot: State=ACTIVE, Pot=120, Stack=410
FoldBot: State=FOLDED, Pot=0, Stack=940
--------------------------- Hand: 6 | Street: RIVER ----------------------------
Community cards: ['8d', '5s', '3c', '3s', '8s']
Current pot size: 240. Current bet: 0. Minimum raise size: 0.
[CallBot] checks. Remaining stack: 1410.
Current pot size: 240. Current bet: 0. Minimum raise size: 0.
[AggroBot] bets 40. Remaining stack: 370.
Current pot size: 280. Current bet: 40. Minimum raise size: 40.
[CallBot] calls. Remaining stack: 1370.
Current pot size: 320. Current bet: 40. Minimum raise size: 40.
Player standings after the betting round:
CallBot: State=ACTIVE, Pot=160, Stack=1370
AggroBot: State=ACTIVE, Pot=160, Stack=370
FoldBot: State=FOLDED, Pot=0, Stack=940
------------------------------ Hand: 6 | SHOWDOWN ------------------------------
CallBot reveals: ['Jd', 'Qs']. Best hand: ['Qs', '8d', '3c', '3s', '8s'] (TWO_PAIR). Hand score: 308.03119999999996.
AggroBot reveals: ['2d', '6d']. Best hand: ['6d', '8d', '3c', '3s', '8s'] (TWO_PAIR). Hand score: 308.0306.
CallBot wins 320.
Player stacks after showdown:
CallBot: 1690
AggroBot: 370
FoldBot: 940
==================================== Hand 7 ====================================
CallBot is on the button.
AggroBot is the small blind.
FoldBot is the big blind.
CallBot is under the gun.
Player stacks at the beginning of hand 7:
CallBot: 1690
AggroBot: 370
FoldBot: 940
-------------------------- Hand: 7 | Street: PRE_FLOP --------------------------
Community cards: None
Current pot size: 30. Current bet: 20. Minimum raise size: 20.
[CallBot] calls. Remaining stack: 1670.
Current pot size: 50. Current bet: 20. Minimum raise size: 20.
[AggroBot] raises bet to 40. Remaining stack: 330.
Current pot size: 80. Current bet: 40. Minimum raise size: 20.
[FoldBot] folds. Remaining stack: 920.
Current pot size: 80. Current bet: 40. Minimum raise size: 20.
[CallBot] calls. Remaining stack: 1650.
Current pot size: 100. Current bet: 40. Minimum raise size: 20.
Player standings after the betting round:
CallBot: State=ACTIVE, Pot=40, Stack=1650
AggroBot: State=ACTIVE, Pot=40, Stack=330
FoldBot: State=FOLDED, Pot=20, Stack=920
---------------------------- Hand: 7 | Street: FLOP ----------------------------
Community cards: ['Ks', '3c', 'Qh']
Current pot size: 100. Current bet: 0. Minimum raise size: 0.
[AggroBot] bets 40. Remaining stack: 290.
Current pot size: 140. Current bet: 40. Minimum raise size: 40.
[CallBot] calls. Remaining stack: 1610.
Current pot size: 180. Current bet: 40. Minimum raise size: 40.
Player standings after the betting round:
CallBot: State=ACTIVE, Pot=80, Stack=1610
AggroBot: State=ACTIVE, Pot=80, Stack=290
FoldBot: State=FOLDED, Pot=20, Stack=920
---------------------------- Hand: 7 | Street: TURN ----------------------------
Community cards: ['Ks', '3c', 'Qh', '7d']
Current pot size: 180. Current bet: 0. Minimum raise size: 0.
[AggroBot] bets 40. Remaining stack: 250.
Current pot size: 220. Current bet: 40. Minimum raise size: 40.
[CallBot] calls. Remaining stack: 1570.
Current pot size: 260. Current bet: 40. Minimum raise size: 40.
Player standings after the betting round:
CallBot: State=ACTIVE, Pot=120, Stack=1570
AggroBot: State=ACTIVE, Pot=120, Stack=250
FoldBot: State=FOLDED, Pot=20, Stack=920
--------------------------- Hand: 7 | Street: RIVER ----------------------------
Community cards: ['Ks', '3c', 'Qh', '7d', '3s']
Current pot size: 260. Current bet: 0. Minimum raise size: 0.
[AggroBot] bets 40. Remaining stack: 210.
Current pot size: 300. Current bet: 40. Minimum raise size: 40.
[CallBot] calls. Remaining stack: 1530.
Current pot size: 340. Current bet: 40. Minimum raise size: 40.
Player standings after the betting round:
CallBot: State=ACTIVE, Pot=160, Stack=1530
AggroBot: State=ACTIVE, Pot=160, Stack=210
FoldBot: State=FOLDED, Pot=20, Stack=920
------------------------------ Hand: 7 | SHOWDOWN ------------------------------
CallBot reveals: ['9s', '4s']. Best hand: ['9s', 'Ks', '3c', 'Qh', '3s'] (PAIR). Hand score: 203.131209.
AggroBot reveals: ['8c', 'Th']. Best hand: ['Th', 'Ks', '3c', 'Qh', '3s'] (PAIR). Hand score: 203.13121.
AggroBot wins 340.
Player stacks after showdown:
CallBot: 1530
AggroBot: 550
FoldBot: 920
==================================== Hand 8 ====================================
AggroBot is on the button.
FoldBot is the small blind.
CallBot is the big blind.
AggroBot is under the gun.
Player stacks at the beginning of hand 8:
CallBot: 1530
AggroBot: 550
FoldBot: 920
-------------------------- Hand: 8 | Street: PRE_FLOP --------------------------
Community cards: None
Current pot size: 30. Current bet: 20. Minimum raise size: 20.
[AggroBot] raises bet to 40. Remaining stack: 510.
Current pot size: 70. Current bet: 40. Minimum raise size: 20.
[FoldBot] folds. Remaining stack: 910.
Current pot size: 70. Current bet: 40. Minimum raise size: 20.
[CallBot] calls. Remaining stack: 1490.
Current pot size: 90. Current bet: 40. Minimum raise size: 20.
Player standings after the betting round:
CallBot: State=ACTIVE, Pot=40, Stack=1490
AggroBot: State=ACTIVE, Pot=40, Stack=510
FoldBot: State=FOLDED, Pot=10, Stack=910
---------------------------- Hand: 8 | Street: FLOP ----------------------------
Community cards: ['6s', '5c', '9d']
Current pot size: 90. Current bet: 0. Minimum raise size: 0.
[CallBot] checks. Remaining stack: 1490.
Current pot size: 90. Current bet: 0. Minimum raise size: 0.
[AggroBot] bets 40. Remaining stack: 470.
Current pot size: 130. Current bet: 40. Minimum raise size: 40.
[CallBot] calls. Remaining stack: 1450.
Current pot size: 170. Current bet: 40. Minimum raise size: 40.
Player standings after the betting round:
CallBot: State=ACTIVE, Pot=80, Stack=1450
AggroBot: State=ACTIVE, Pot=80, Stack=470
FoldBot: State=FOLDED, Pot=10, Stack=910
---------------------------- Hand: 8 | Street: TURN ----------------------------
Community cards: ['6s', '5c', '9d', 'Js']
Current pot size: 170. Current bet: 0. Minimum raise size: 0.
[CallBot] checks. Remaining stack: 1450.
Current pot size: 170. Current bet: 0. Minimum raise size: 0.
[AggroBot] bets 40. Remaining stack: 430.
Current pot size: 210. Current bet: 40. Minimum raise size: 40.
[CallBot] calls. Remaining stack: 1410.
Current pot size: 250. Current bet: 40. Minimum raise size: 40.
Player standings after the betting round:
CallBot: State=ACTIVE, Pot=120, Stack=1410
AggroBot: State=ACTIVE, Pot=120, Stack=430
FoldBot: State=FOLDED, Pot=10, Stack=910
--------------------------- Hand: 8 | Street: RIVER ----------------------------
Community cards: ['6s', '5c', '9d', 'Js', '4c']
Current pot size: 250. Current bet: 0. Minimum raise size: 0.
[CallBot] checks. Remaining stack: 1410.
Current pot size: 250. Current bet: 0. Minimum raise size: 0.
[AggroBot] bets 40. Remaining stack: 390.
Current pot size: 290. Current bet: 40. Minimum raise size: 40.
[CallBot] calls. Remaining stack: 1370.
Current pot size: 330. Current bet: 40. Minimum raise size: 40.
Player standings after the betting round:
CallBot: State=ACTIVE, Pot=160, Stack=1370
AggroBot: State=ACTIVE, Pot=160, Stack=390
FoldBot: State=FOLDED, Pot=10, Stack=910
------------------------------ Hand: 8 | SHOWDOWN ------------------------------
CallBot reveals: ['3d', 'Ad']. Best hand: ['Ad', '6s', '5c', '9d', 'Js'] (HIGH_CARD). Hand score: 100.1411090605.
AggroBot reveals: ['As', 'Qd']. Best hand: ['As', 'Qd', '6s', '9d', 'Js'] (HIGH_CARD). Hand score: 100.1412110906.
AggroBot wins 330.
Player stacks after showdown:
CallBot: 1370
AggroBot: 720
FoldBot: 910
==================================== Hand 9 ====================================
FoldBot is on the button.
CallBot is the small blind.
AggroBot is the big blind.
FoldBot is under the gun.
Player stacks at the beginning of hand 9:
CallBot: 1370
AggroBot: 720
FoldBot: 910
-------------------------- Hand: 9 | Street: PRE_FLOP --------------------------
Community cards: None
Current pot size: 30. Current bet: 20. Minimum raise size: 20.
[FoldBot] folds. Remaining stack: 910.
Current pot size: 30. Current bet: 20. Minimum raise size: 20.
[CallBot] calls. Remaining stack: 1350.
Current pot size: 40. Current bet: 20. Minimum raise size: 20.
[AggroBot] raises bet to 40. Remaining stack: 680.
Current pot size: 60. Current bet: 40. Minimum raise size: 20.
[CallBot] calls. Remaining stack: 1330.
Current pot size: 80. Current bet: 40. Minimum raise size: 20.
Player standings after the betting round:
CallBot: State=ACTIVE, Pot=40, Stack=1330
AggroBot: State=ACTIVE, Pot=40, Stack=680
FoldBot: State=FOLDED, Pot=0, Stack=910
---------------------------- Hand: 9 | Street: FLOP ----------------------------
Community cards: ['9d', '7s', 'Qd']
Current pot size: 80. Current bet: 0. Minimum raise size: 0.
[CallBot] checks. Remaining stack: 1330.
Current pot size: 80. Current bet: 0. Minimum raise size: 0.
[AggroBot] bets 40. Remaining stack: 640.
Current pot size: 120. Current bet: 40. Minimum raise size: 40.
[CallBot] calls. Remaining stack: 1290.
Current pot size: 160. Current bet: 40. Minimum raise size: 40.
Player standings after the betting round:
CallBot: State=ACTIVE, Pot=80, Stack=1290
AggroBot: State=ACTIVE, Pot=80, Stack=640
FoldBot: State=FOLDED, Pot=0, Stack=910
---------------------------- Hand: 9 | Street: TURN ----------------------------
Community cards: ['9d', '7s', 'Qd', 'Kh']
Current pot size: 160. Current bet: 0. Minimum raise size: 0.
[CallBot] checks. Remaining stack: 1290.
Current pot size: 160. Current bet: 0. Minimum raise size: 0.
[AggroBot] bets 40. Remaining stack: 600.
Current pot size: 200. Current bet: 40. Minimum raise size: 40.
[CallBot] calls. Remaining stack: 1250.
Current pot size: 240. Current bet: 40. Minimum raise size: 40.
Player standings after the betting round:
CallBot: State=ACTIVE, Pot=120, Stack=1250
AggroBot: State=ACTIVE, Pot=120, Stack=600
FoldBot: State=FOLDED, Pot=0, Stack=910
--------------------------- Hand: 9 | Street: RIVER ----------------------------
Community cards: ['9d', '7s', 'Qd', 'Kh', 'Qs']
Current pot size: 240. Current bet: 0. Minimum raise size: 0.
[CallBot] checks. Remaining stack: 1250.
Current pot size: 240. Current bet: 0. Minimum raise size: 0.
[AggroBot] bets 40. Remaining stack: 560.
Current pot size: 280. Current bet: 40. Minimum raise size: 40.
[CallBot] calls. Remaining stack: 1210.
Current pot size: 320. Current bet: 40. Minimum raise size: 40.
Player standings after the betting round:
CallBot: State=ACTIVE, Pot=160, Stack=1210
AggroBot: State=ACTIVE, Pot=160, Stack=560
FoldBot: State=FOLDED, Pot=0, Stack=910
------------------------------ Hand: 9 | SHOWDOWN ------------------------------
CallBot reveals: ['5c', '4s']. Best hand: ['9d', '7s', 'Qd', 'Kh', 'Qs'] (PAIR). Hand score: 212.130907.
AggroBot reveals: ['6h', '3h']. Best hand: ['9d', '7s', 'Qd', 'Kh', 'Qs'] (PAIR). Hand score: 212.130907.
CallBot wins 160.
AggroBot wins 160.
Player stacks after showdown:
CallBot: 1370
AggroBot: 720
FoldBot: 910
=================================== Hand 10 ====================================
CallBot is on the button.
AggroBot is the small blind.
FoldBot is the big blind.
CallBot is under the gun.
Player stacks at the beginning of hand 10:
CallBot: 1370
AggroBot: 720
FoldBot: 910
------------------------- Hand: 10 | Street: PRE_FLOP --------------------------
Community cards: None
Current pot size: 30. Current bet: 20. Minimum raise size: 20.
[CallBot] calls. Remaining stack: 1350.
Current pot size: 50. Current bet: 20. Minimum raise size: 20.
[AggroBot] raises bet to 40. Remaining stack: 680.
Current pot size: 80. Current bet: 40. Minimum raise size: 20.
[FoldBot] folds. Remaining stack: 890.
Current pot size: 80. Current bet: 40. Minimum raise size: 20.
[CallBot] calls. Remaining stack: 1330.
Current pot size: 100. Current bet: 40. Minimum raise size: 20.
Player standings after the betting round:
CallBot: State=ACTIVE, Pot=40, Stack=1330
AggroBot: State=ACTIVE, Pot=40, Stack=680
FoldBot: State=FOLDED, Pot=20, Stack=890
--------------------------- Hand: 10 | Street: FLOP ----------------------------
Community cards: ['Kd', 'Ks', 'Ts']
Current pot size: 100. Current bet: 0. Minimum raise size: 0.
[AggroBot] bets 40. Remaining stack: 640.
Current pot size: 140. Current bet: 40. Minimum raise size: 40.
[CallBot] calls. Remaining stack: 1290.
Current pot size: 180. Current bet: 40. Minimum raise size: 40.
Player standings after the betting round:
CallBot: State=ACTIVE, Pot=80, Stack=1290
AggroBot: State=ACTIVE, Pot=80, Stack=640
FoldBot: State=FOLDED, Pot=20, Stack=890
--------------------------- Hand: 10 | Street: TURN ----------------------------
Community cards: ['Kd', 'Ks', 'Ts', '8c']
Current pot size: 180. Current bet: 0. Minimum raise size: 0.
[AggroBot] bets 40. Remaining stack: 600.
Current pot size: 220. Current bet: 40. Minimum raise size: 40.
[CallBot] calls. Remaining stack: 1250.
Current pot size: 260. Current bet: 40. Minimum raise size: 40.
Player standings after the betting round:
CallBot: State=ACTIVE, Pot=120, Stack=1250
AggroBot: State=ACTIVE, Pot=120, Stack=600
FoldBot: State=FOLDED, Pot=20, Stack=890
--------------------------- Hand: 10 | Street: RIVER ---------------------------
Community cards: ['Kd', 'Ks', 'Ts', '8c', '4d']
Current pot size: 260. Current bet: 0. Minimum raise size: 0.
[AggroBot] bets 40. Remaining stack: 560.
Current pot size: 300. Current bet: 40. Minimum raise size: 40.
[CallBot] calls. Remaining stack: 1210.
Current pot size: 340. Current bet: 40. Minimum raise size: 40.
Player standings after the betting round:
CallBot: State=ACTIVE, Pot=160, Stack=1210
AggroBot: State=ACTIVE, Pot=160, Stack=560
FoldBot: State=FOLDED, Pot=20, Stack=890
----------------------------- Hand: 10 | SHOWDOWN ------------------------------
CallBot reveals: ['6d', '7c']. Best hand: ['7c', 'Kd', 'Ks', 'Ts', '8c'] (PAIR). Hand score: 213.100807.
AggroBot reveals: ['Ad', '8h']. Best hand: ['Ad', '8h', 'Kd', 'Ks', '8c'] (TWO_PAIR). Hand score: 313.0814.
AggroBot wins 340.
Player stacks after showdown:
CallBot: 1210
AggroBot: 900
FoldBot: 890
import pandas as pd
from maverick import Street, GameEventType, GameStage
df = pd.DataFrame(event_listener.dump)
df["street"] = pd.to_numeric(df["street"], errors="coerce").astype("UInt8")
df["stage"] = pd.to_numeric(df["stage"], errors="coerce").astype("UInt8")
df["hand_number"] = pd.to_numeric(df["hand_number"], errors="coerce").astype("UInt8")
df.rename(
columns={
"type": "event_type_value",
"stage": "stage_value",
"street": "street_value",
"ts": "event_ts",
"id": "event_id",
},
inplace=True,
)
# Map enum values to names for better readability
street_map = {s.value: s.name for s in Street}
df["street_name"] = df["street_value"].map(street_map)
# Map enum values to names for better readability
event_type_map = {e.value: e.name for e in GameEventType}
df["event_type_name"] = df["event_type_value"].map(event_type_map)
# Map enum values to names for better readability
game_stage_map = {s.value: s.name for s in GameStage}
df["game_stage_name"] = df["stage_value"].map(game_stage_map)
# Add a unique game_uid to group events from the same game together
df["game_uid"] = game.game_uid
df.head()
| event_id | event_ts | event_type_value | hand_number | street_value | stage_value | player_id | action | payload | street_name | event_type_name | game_stage_name | game_uid | |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 0 | 252042d5feb944ad8332d1a5992e57fa | 1.773855e+09 | 1 | 0 | <NA> | 3 | None | None | {} | NaN | GAME_STARTED | STARTED | 363de64bf62249e0835986da381d2faa |
| 1 | a46038fd42164886a7fb276afeea1e50 | 1.773855e+09 | 3 | 1 | 0 | 4 | None | None | {} | PRE_FLOP | HAND_STARTED | DEALING | 363de64bf62249e0835986da381d2faa |
| 2 | 8d9624b42a574164a62901dd6f1550a0 | 1.773855e+09 | 7 | 1 | 0 | 4 | None | None | {} | PRE_FLOP | HOLE_CARDS_DEALT | DEALING | 363de64bf62249e0835986da381d2faa |
| 3 | a2418587377749bbbc95a32b9eaae538 | 1.773855e+09 | 17 | 1 | 0 | 4 | None | None | {} | PRE_FLOP | BLINDS_POSTED | DEALING | 363de64bf62249e0835986da381d2faa |
| 4 | e1acbbed0ed146f0845238a32ca6f778 | 1.773855e+09 | 18 | 1 | 0 | 4 | None | None | {} | PRE_FLOP | ANTES_POSTED | DEALING | 363de64bf62249e0835986da381d2faa |