def __init__(self, starting_stacks): # Must have at least 1 player assert len(starting_stacks) > 1 self.game_started = False self.action_index = 0 self.game = Game(starting_stacks=starting_stacks)
def test_is_all_in(): game = Game(starting_stacks=[100, 200, 10]) game.add_action(Action(0, Move.SMALL_BLIND, total_bet=1, amount_added=1)) game.add_action(Action(1, Move.BIG_BLIND, total_bet=2, amount_added=2)) game.add_action(Action(2, Move.BET_RAISE, total_bet=10, amount_added=10)) assert game.view().is_all_in() == [False, False, True]
def test_blinds(): game = Game(starting_stacks=[10, 20, 100]) assert game.view().small_blind() == Action(0, Move.SMALL_BLIND, total_bet=1, amount_added=1) game.add_action(game.view().small_blind()) assert game.view().big_blind() == Action(1, Move.BIG_BLIND, total_bet=2, amount_added=2)
def test_street_over_all_fold(): game = Game(starting_stacks=[100, 200, 300]) game.add_action(game.view().small_blind()) game.add_action(game.view().big_blind()) game.add_action(game.view().bet_raise(to=10)) game.add_action(game.view().fold()) game.add_action(game.view().fold()) assert rules.street_over(game.view()) is True game.set_street(Street.FLOP) assert rules.street_over(game.view()) is True game.set_street(Street.TURN) assert rules.street_over(game.view()) is True game.set_street(Street.RIVER) assert rules.street_over(game.view()) is True
def test_street_over(): game = Game(starting_stacks=[100, 200, 300]) assert rules.street_over(game.view()) is False game.add_action(game.view().small_blind()) assert rules.street_over(game.view()) is False game.add_action(game.view().big_blind()) assert rules.street_over(game.view()) is False game.add_action(game.view().bet_raise(to=10)) assert rules.street_over(game.view()) is False game.add_action(game.view().call()) assert rules.street_over(game.view()) is False game.add_action(game.view().call()) assert rules.street_over(game.view()) is True # Flop game.set_street(Street.FLOP) assert rules.street_over(game.view()) is False game.add_action(game.view().call()) assert rules.street_over(game.view()) is False game.add_action(game.view().call()) assert rules.street_over(game.view()) is False game.add_action(game.view().call()) assert rules.street_over(game.view()) is True # Turn game.set_street(Street.TURN) assert rules.street_over(game.view()) is False game.add_action(game.view().bet_raise(to=20)) assert rules.street_over(game.view()) is False game.add_action(game.view().fold()) assert rules.street_over(game.view()) is False game.add_action(game.view().call()) assert rules.street_over(game.view()) is True # River game.set_street(Street.RIVER) assert rules.street_over(game.view()) is False game.add_action(game.view().call()) assert rules.street_over(game.view()) is False game.add_action(game.view().bet_raise(to=30)) assert rules.street_over(game.view()) is False game.add_action(game.view().call()) assert rules.street_over(game.view()) is True
def test_amount_bet(): game = Game(starting_stacks=[100, 200, 300]) preflop_action = [ Action(0, Move.SMALL_BLIND, total_bet=1, amount_added=1), Action(1, Move.BIG_BLIND, total_bet=2, amount_added=2), Action(2, Move.BET_RAISE, total_bet=6, amount_added=6), ] for a in preflop_action: game.add_action(a) assert game.view().amount_added_in_street() == [1, 2, 6] game.set_street(Street.FLOP) flop_action = [ Action(0, Move.CHECK_CALL, total_bet=0, amount_added=0), Action(1, Move.BET_RAISE, total_bet=10, amount_added=10), Action(2, Move.FOLD, amount_added=0, total_bet=10), Action(0, Move.FOLD, amount_added=0, total_bet=10), ] for a in flop_action: game.add_action(a) assert game.view().amount_added_in_street() == [0, 10, 0] assert game.view().amount_added_total() == [1, 12, 6]
def test_num_players(): game = Game(starting_stacks=[100, 200, 300]) assert game.num_players() == 3 assert game.view().num_players() == 3
def test_call_all_in(): game = Game(starting_stacks=[10, 20, 100]) game.add_action(Action(0, Move.SMALL_BLIND, total_bet=1, amount_added=1)) game.add_action(Action(1, Move.BIG_BLIND, total_bet=2, amount_added=2)) game.add_action(Action(2, Move.BET_RAISE, total_bet=100, amount_added=100)) call = game.view().call() assert game.view().call() == Action(player_index=0, move=Move.CHECK_CALL, amount_added=9, total_bet=100) game.add_action(call) call = game.view().call() assert call == Action(player_index=1, move=Move.CHECK_CALL, amount_added=18, total_bet=100)
def test_is_folded(): game = Game(starting_stacks=[100, 200, 300]) game.add_action(Action(0, Move.SMALL_BLIND, total_bet=1, amount_added=1)) game.add_action(Action(1, Move.BIG_BLIND, total_bet=2, amount_added=2)) game.add_action(Action(2, Move.FOLD, total_bet=2, amount_added=0)) assert game.view().is_folded() == [False, False, True] game.add_action(Action(1, Move.CHECK_CALL, total_bet=2, amount_added=1)) game.add_action(Action(2, Move.CHECK_CALL, total_bet=2, amount_added=0)) assert game.view().is_folded() == [False, False, True] game.set_street(Street.TURN) assert game.view().is_folded() == [False, False, True] game.add_action(Action(0, Move.BET_RAISE, total_bet=10, amount_added=10)) game.add_action(Action(1, Move.FOLD, total_bet=10, amount_added=0)) assert game.view().is_folded() == [False, True, True]
def test_latest_bet_raise_amount(): game = Game(starting_stacks=[100, 200, 300]) assert game.view().last_raise_amount() == 0 game.add_action(Action(0, Move.SMALL_BLIND, total_bet=1, amount_added=1)) assert game.view().last_raise_amount() == 1 assert game.view().current_bet_amount() == 1 game.add_action(Action(1, Move.BIG_BLIND, total_bet=2, amount_added=2)) assert game.view().last_raise_amount() == 1 assert game.view().current_bet_amount() == 2 game.add_action(Action(2, Move.BET_RAISE, total_bet=10, amount_added=10)) assert game.view().last_raise_amount() == 8 assert game.view().current_bet_amount() == 10 # Raise to 20 total. This is a raise of 8 on top of the original 10. # It is a min-raise. game.add_action( Action(0, Move.BET_RAISE, total_bet=18, amount_added=18 - 1)) assert game.view().last_raise_amount() == 8 assert game.view().current_bet_amount() == 18 # Riase it to 30 total (up from the previous 18). This is a raise of 12. game.add_action( Action(1, Move.BET_RAISE, total_bet=30, amount_added=30 - 2)) assert game.view().last_raise_amount() == 12 assert game.view().current_bet_amount() == 30
def test_bet_and_call_amount(): game = Game(starting_stacks=[100, 200, 300]) assert game.view().current_bet_amount() == 0 assert game.view().amount_to_call() == [0, 0, 0] game.add_action(Action(0, Move.SMALL_BLIND, total_bet=1, amount_added=1)) assert game.view().current_bet_amount() == 1 assert game.view().amount_to_call() == [0, 1, 1] game.add_action(Action(1, Move.BIG_BLIND, total_bet=2, amount_added=2)) game.add_action(Action(2, Move.BET_RAISE, total_bet=10, amount_added=10)) assert game.view().current_bet_amount() == 10 assert game.view().amount_to_call() == [9, 8, 0] game.add_action(Action(0, Move.CHECK_CALL, total_bet=10, amount_added=9)) game.add_action(Action(1, Move.CHECK_CALL, total_bet=10, amount_added=8)) assert game.view().current_bet_amount() == 10 assert game.view().amount_to_call() == [0, 0, 0]
def test_action_views(): game = Game(starting_stacks=[100, 200, 300]) preflop_action = [ Action(0, Move.SMALL_BLIND, total_bet=1, amount_added=1), Action(1, Move.BIG_BLIND, total_bet=2, amount_added=2), Action(2, Move.BET_RAISE, total_bet=6, amount_added=6), Action(0, Move.CHECK_CALL, total_bet=6, amount_added=5), Action(1, Move.CHECK_CALL, total_bet=6, amount_added=4), ] for a in preflop_action: game.add_action(a) assert game.current_street() == Street.PREFLOP assert game.events == preflop_action preflop_view = game.view() assert preflop_view.street_action() == preflop_action assert preflop_view.all_actions() == preflop_action game.set_street(Street.FLOP) flop_action = [ Action(0, Move.CHECK_CALL, total_bet=0, amount_added=0), Action(1, Move.BET_RAISE, total_bet=10, amount_added=10), Action(2, Move.FOLD, total_bet=10, amount_added=0), Action(0, Move.FOLD, total_bet=10, amount_added=0), ] for a in flop_action: game.add_action(a) assert game.current_street() == Street.FLOP assert game.events == preflop_action + [Street.FLOP] + flop_action # assert preflop_view.timestamp == assert preflop_view.street_action() == preflop_action assert preflop_view.all_actions() == preflop_action # Recreate the preflop view preflop_view = game.view(timestamp=5) assert preflop_view.street_action() == preflop_action assert preflop_view.all_actions() == preflop_action flop_view = game.view() assert flop_view.street_action() == flop_action assert flop_view.all_actions() == preflop_action + flop_action # Test a view in the middle of the preflop mid_preflop_view = game.view(3) assert mid_preflop_view.street_action() == [ Action(0, Move.SMALL_BLIND, total_bet=1, amount_added=1), Action(1, Move.BIG_BLIND, total_bet=2, amount_added=2), Action(2, Move.BET_RAISE, total_bet=6, amount_added=6), ]
def test_stack_sizes(): game = Game(starting_stacks=[100, 200, 300]) assert game.view().current_stack_sizes() == [100, 200, 300] game.add_action(Action(0, Move.SMALL_BLIND, total_bet=1, amount_added=1)) game.add_action(Action(1, Move.BIG_BLIND, total_bet=2, amount_added=2)) game.add_action(Action(2, Move.BET_RAISE, total_bet=6, amount_added=6)) assert game.view().current_stack_sizes() == [99, 198, 294] game.add_action(Action(0, Move.CHECK_CALL, total_bet=6, amount_added=5)) game.add_action(Action(1, Move.CHECK_CALL, total_bet=6, amount_added=4)) assert game.view().current_stack_sizes() == [94, 194, 294] game.set_street(Street.TURN) game.add_action(Action(0, Move.CHECK_CALL, total_bet=0, amount_added=0)) game.add_action(Action(1, Move.BET_RAISE, total_bet=10, amount_added=10)) assert game.view().current_stack_sizes() == [94, 184, 294]
class GameRunner: def __init__(self, starting_stacks): # Must have at least 1 player assert len(starting_stacks) > 1 self.game_started = False self.action_index = 0 self.game = Game(starting_stacks=starting_stacks) def game_view(self): return self.game.view() def current_player(self): return self.game_view().current_player() def street(self): return self.game_view().street() def start_game(self): # Small/Big Blind self.game_started = True self.game.set_street(Street.PREFLOP) self.add_small_blind() self.add_big_blind() def advance(self, action: Action) -> ActionResult: if not self.game_started: raise Exception("Game not started") player_index = self.game_view().current_player() action_result = rules.action_valid( action_index=self.action_index, player_index=player_index, action=action, game=self.game_view(), ) # Validate the action if player_index != action.player_index: raise Exception("Wrong Player") if not action_result.is_valid(): logger.error("Action is invalid %s %s", action, action_result) raise ActionError(self.game_view(), action, action_result) self.game.add_action(action) self.action_index += 1 player_index = self.game_view().current_player() if self.all_but_one_player_folded(): return self._end_hand() while rules.street_over(self.game_view()): self._advance_street() if self.street() == Street.HAND_OVER: break # Return the current state of the game if self.game_view().street() == Street.HAND_OVER: return ActionResult(street=self.game_view().street()) else: return ActionResult( street=self.game_view().street(), current_player=self.game_view().current_player(), total_bet=self.game_view().current_bet_amount(), amount_to_call=self.game_view().amount_to_call()[player_index], ) def add_small_blind(self) -> ActionResult: return self.advance(self.game_view().small_blind()) def add_big_blind(self) -> ActionResult: return self.advance(self.game_view().big_blind()) def call(self) -> ActionResult: return self.advance(self.game_view().call()) def check(self) -> ActionResult: return self.advance(self.game_view().check()) def bet_raise(self, to: Optional[int] = None, raise_amount: Optional[int] = None) -> ActionResult: return self.advance(self.game_view().bet_raise( to=to, raise_amount=raise_amount)) def fold(self) -> ActionResult: return self.advance(self.game_view().fold()) def _advance_street(self): if self.game_view().street() == Street.PREFLOP: self.game.set_street(Street.FLOP) elif self.game_view().street() == Street.FLOP: self.game.set_street(Street.TURN) elif self.game_view().street() == Street.TURN: self.game.set_street(Street.RIVER) elif self.game_view().street() == Street.RIVER: self.game.set_street(Street.HAND_OVER) else: raise Exception() def _end_hand(self): self.game.set_street(Street.HAND_OVER) return ActionResult(street=self.game_view().street()) def all_but_one_player_folded(self): num_not_folded = 0 for is_folded in self.game_view().is_folded(): if not is_folded: num_not_folded += 1 return num_not_folded == 1 def all_players_all_in(self): num_not_all_in = 0 for is_all_in in self.game_view().is_all_in(): if not is_all_in: num_not_all_in += 1 return num_not_all_in == 0