uoftcprg / pokerkit

An open-source Python library for poker game simulations, hand evaluations, and statistical analysis
https://pokerkit.readthedocs.io/
MIT License
247 stars 29 forks source link

How to all-in? #11

Closed huynq55 closed 4 months ago

huynq55 commented 4 months ago

I'm trying to use the library to build a game tree. However, I do not know how to apply all-in action to a state. Do I need to code this function my self?

huynq55 commented 4 months ago

I wrote my own function as follow:


def apply_action(self, action):
        match action:
            case "fold":
                self.state.fold()
            case "all_in":
                self.state.complete_bet_or_raise_to(self.state.stacks[self.state.actor_index] + self.state.bets[self.state.actor_index])

And run it with:

a = EnhancedState()
a.state.deal_hole('AsAd')
a.state.deal_hole('KsKd')
a.state.complete_bet_or_raise_to(200)
a.state.complete_bet_or_raise_to(500)
a.apply_action('all_in')
a.apply_action('all_in')
print(a.state.all_in_status)

I got this error message:

Traceback (most recent call last):
  File "/home/huy/my_poker/enhanced_state.py", line 90, in <module>
    a.apply_action('all_in')
  File "/home/huy/my_poker/enhanced_state.py", line 45, in apply_action
    self.state.complete_bet_or_raise_to(self.state.stacks[self.state.actor_index] + self.state.bets[self.state.actor_index])
  File "/home/huy/miniconda3/envs/poker_kit/lib/python3.11/site-packages/pokerkit/state.py", line 4246, in complete_bet_or_raise_to
    amount = self.verify_completion_betting_or_raising_to(amount)
             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/huy/miniconda3/envs/poker_kit/lib/python3.11/site-packages/pokerkit/state.py", line 4094, in verify_completion_betting_or_raising_to
    self._verify_completion_betting_or_raising()
  File "/home/huy/miniconda3/envs/poker_kit/lib/python3.11/site-packages/pokerkit/state.py", line 4070, in _verify_completion_betting_or_raising
    raise ValueError('There are not enough chips in stack.')
ValueError: There are not enough chips in stack.

So I can not make two people both all-in using the code above.

AussieSeaweed commented 4 months ago

Your way of handling all-in in 'apply_action' is correct. A more elegant way is by doing self.state.complete_bet_or_raise_to(self.state.max_completion_betting_or_raising_to_amount), but your method is correct too.

def apply_action(self, action):
        match action:
            case "fold":
                self.state.fold()
            case "all_in":
                self.state.complete_bet_or_raise_to(self.state.max_completion_betting_or_raising_to_amount)

The problem, however, is in your second code snippet: the latter call of a.apply_action('all_in'). What happened just before this call is that the former player raised all-in. Since the latter actor's stack is covered by the former actor, the latter actor cannot bet or raise since he/she is already covered by the former's all-in. Therefore the latter actor can only fold or call. Part of the problem is that the PokerKit's error message was not clear enough, that is my mistake.

There are two ways you can fix this:

  1. Instead of all-inning, simply call (or fold, but this will not all-in).
a = EnhancedState()
a.state.deal_hole('AsAd')
a.state.deal_hole('KsKd')
a.state.complete_bet_or_raise_to(200)
a.state.complete_bet_or_raise_to(500)
a.apply_action('all_in')
# a.apply_action('all_in')
a.state.check_or_call()  # ``a.state.fold()`` is possible too, but this will fold, not all-in
print(a.state.all_in_status)
  1. Make all-in also mean call "all-in", not just betting/raising.
def apply_action(self, action):
        match action:
            case "fold":
                self.state.fold()
            case "all_in":
                if self.state.can_complete_bet_or_raise_to():
                    self.state.complete_bet_or_raise_to(self.state.max_completion_betting_or_raising_to_amount)
                else:
                    self.state.check_or_call()