GithubHelp home page GithubHelp logo

ishikota / pypokerengine Goto Github PK

View Code? Open in Web Editor NEW
593.0 36.0 182.0 677 KB

Poker engine for poker AI development in Python

Home Page: https://ishikota.github.io/PyPokerEngine/

License: MIT License

Python 100.00%
ai-poker-game poker-engine reinforcement-learning

pypokerengine's People

Contributors

ishikota avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

pypokerengine's Issues

TypeError: slice indices must be integers or None or have an __index__ method

File "c:\users\caocao\anaconda3\lib\site-packages\pypokergui\server\poker.py", line 75, in on_message
MM.broadcast_update_game(self, global_game_manager, self.sockets, MODE_SPEED)
File "c:\users\caocao\anaconda3\lib\site-packages\pypokergui\server\message_manager.py", line 82, in broadcast_update_game
message = _gen_game_update_message(handler, update)
File "c:\users\caocao\anaconda3\lib\site-packages\pypokergui\server\message_manager.py", line 114, in _gen_game_update_message
table_html_str = handler.render_string("round_state.html", round_state=round_state)
File "c:\users\caocao\anaconda3\lib\site-packages\tornado\web.py", line 826, in render_string
return t.generate(**namespace)
File "c:\users\caocao\anaconda3\lib\site-packages\tornado\template.py", line 348, in generate
return execute()
File "round_state_html.generated.py", line 53, in _tt_execute
for idx, player in zip(range(len(round_state['seats']))[:len(round_state['seats'])/2], round_state['seats']): # round_state.html:22
TypeError: slice indices must be integers or None or have an index method

Tournaments

There should be a functionality to run tournaments where you can set the payouts and rather than simulating a number of hands, simulating a tournament (until one player is left).

5 best cards dont win..

There is an issue that if two Players have the same 5 best cards but one of them has a higher handcard he win. But thats not right cause just the highest 5 cards are important for winning so it should be split between that. Saw it on a straight in middle cards, so all had the same straight but the bot with the highest cards won.

min_raise and max_raise = -1 when raise is still possible

When the players remaining stack is too low for the minimal raise (defined by the call amount + the last raise performed on the street), -1 is given by valid_actions, though if the player has more than the call amount, he should be able to raise to that value (to go all-in)
To fix this, I changed the function legal_actions in engine/action_checker.py to:

def legal_actions(self, players, player_pos, sb_amount):
    min_raise = self.__min_raise_amount(players, sb_amount)
    max_raise = players[player_pos].stack + players[player_pos].paid_sum()
    if max_raise < min_raise:
      min_raise = max_raise = -1
        if self.agree_amount(players)>=max_raise:
            min_raise = max_raise = -1
        else:
            min_raise = max_raise = players[player_pos].stack + players[player_pos].paid_sum()
    return [
        { "action" : "fold" , "amount" : 0 },
        { "action" : "call" , "amount" : self.agree_amount(players) },
        { "action" : "raise", "amount" : { "min": min_raise, "max": max_raise } }
]

Now if the player has a stack smaller than the call amount, -1 is still returned and the player can just call, but when the player's stack is larger than the call amount, his all-in amount is returned.

It's too slow!!!

PyPokerEngine is a very good framwork for poker AI development.but it is too slow!

I test it use the FishPlayer, and run 10 rounds,it take 10s on my computer.
I test another repo, https://github.com/chasembowers/poker-learn ,it can run 10000 rounds in 1 minute on my computer.

So, I use PyCharm Profile to check it.
the function _calc_hand_info_flg take more than 70% time.

Finally,I recommend use https://github.com/worldveil/deuces to speed up.
a lot of repo on github are using deuces
it's on py2, maybe you can use the fork version https://github.com/ihendley/treys

ValueError: Unexpected action 10 received

Hello i cant run the program because it has error. Somebody help me pls T_T

Here is the error code:

Traceback (most recent call last):
File "C:/Users/Vince/PycharmProjects/Poker_Thesis/simulate.py", line 18, in
game_result = start_poker(config, verbose=0)
File "C:\Users\Vince\PycharmProjects\Poker_Thesis\pypokerengine\api\game.py", line 14, in start_poker
result_message = dealer.start_game(config.max_round)
File "C:\Users\Vince\PycharmProjects\Poker_Thesis\pypokerengine\engine\dealer.py", line 39, in start_game
table = self.play_round(round_count, sb_amount, ante, table)
File "C:\Users\Vince\PycharmProjects\Poker_Thesis\pypokerengine\engine\dealer.py", line 49, in play_round
state, msgs = RoundManager.apply_action(state, action, bet_amount)
File "C:\Users\Vince\PycharmProjects\Poker_Thesis\pypokerengine\engine\round_manager.py", line 30, in apply_action
state = self.__update_state_by_action(state, action, bet_amount)
File "C:\Users\Vince\PycharmProjects\Poker_Thesis\pypokerengine\engine\round_manager.py", line 154, in __update_state_by_action
return self.__accept_action(state, action, bet_amount)
File "C:\Users\Vince\PycharmProjects\Poker_Thesis\pypokerengine\engine\round_manager.py", line 170, in __accept_action
raise ValueError("Unexpected action %s received" % action)
ValueError: Unexpected action 10 received

'restore_game_state' raise Exception when ante is ON

error_log

  File "/home/ec2-user/pokeraienv/local/lib/python2.7/site-packages/pypokerengine/api/game.py", line 14, in start_poker
    result_message = dealer.start_game(config.max_round)
  File "/home/ec2-user/pokeraienv/local/lib/python2.7/site-packages/pypokerengine/engine/dealer.py", line 39, in start_game
    table = self.play_round(round_count, sb_amount, ante, table)
  File "/home/ec2-user/pokeraienv/local/lib/python2.7/site-packages/pypokerengine/engine/dealer.py", line 48, in play_round
    action, bet_amount = self.__publish_messages(msgs)
  File "/home/ec2-user/pokeraienv/local/lib/python2.7/site-packages/pypokerengine/engine/dealer.py", line 103, in __publish_messages
    return self.message_handler.process_message(*msgs[-1])
  File "/home/ec2-user/pokeraienv/local/lib/python2.7/site-packages/pypokerengine/engine/dealer.py", line 191, in process_message
    return receiver.respond_to_ask(msg["message"])
  File "/home/ec2-user/pokeraienv/local/lib/python2.7/site-packages/pypokerengine/players.py", line 48, in respond_to_ask
    return self.declare_action(valid_actions, hole_card, round_state)
  File "../../../../../pypokerai/player.py", line 16, in declare_action
    game_state = restore_state(hole_card, round_state)
  File "../../../../../pypokerai/player.py", line 49, in restore_state
    game_state = restore_game_state(round_state)
  File "/home/ec2-user/pokeraienv/local/lib/python2.7/site-packages/pypokerengine/utils/game_state_utils.py", line 16, in restore_game_state
    "table": _restore_table(round_state)
  File "/home/ec2-user/pokeraienv/local/lib/python2.7/site-packages/pypokerengine/utils/game_state_utils.py", line 74, in _restore_table
    table.seats = _restore_seats(round_state["seats"], round_state["action_histories"])
  File "/home/ec2-user/pokeraienv/local/lib/python2.7/site-packages/pypokerengine/utils/game_state_utils.py", line 92, in _restore_seats
    _restore_pay_info_on_players(players, players_state, action_histories)
  File "/home/ec2-user/pokeraienv/local/lib/python2.7/site-packages/pypokerengine/utils/game_state_utils.py", line 118, in _restore_pay_info_on_players
    _restore_pay_info_amount_on_players(players, round_action_histories)
  File "/home/ec2-user/pokeraienv/local/lib/python2.7/site-packages/pypokerengine/utils/game_state_utils.py", line 125, in _restore_pay_info_amount_on_players
    player.pay_info.amount += _fetch_pay_amount(action_history)
  File "/home/ec2-user/pokeraienv/local/lib/python2.7/site-packages/pypokerengine/utils/game_state_utils.py", line 137, in _fetch_pay_amount
    raise Exception("Unexpected type of action_history is passed => %s" % action_history)
Exception: Unexpected type of action_history is passed => {'action': 'ANTE', 'amount': 25, 'uuid': 'suormojqznrqohrgkyiiqc'}

Fix Here by handling ANTE type action_history

#game_state_utils.py
130 def _fetch_pay_amount(action_history):$
131     action = action_history["action"]$
132     if action == Player.ACTION_FOLD_STR: return 0$
133     if action == Player.ACTION_CALL_STR: return action_history["paid"]$
134     if action == Player.ACTION_RAISE_STR: return action_history["paid"]$
135     if action == Player.ACTION_SMALL_BLIND: return action_history["amount"]$
136     if action == Player.ACTION_BIG_BLIND: return action_history["amount"]$
137     raise Exception("Unexpected type of action_history is passed => %s" % action_history)

How about another poker game types?

Are you plan to implement another games, like SNG, MTT tournaments and so on?
In cash game I expect that lost players will rebuy and continue play on the table. Because, what if I need to test 1kk rounds for 9 players?

Hand_evaluator preventing emulator from working

When using the emulator code given in the Readme and error is thrown in the hand_evaluator.py file being:

IndexError: list index out of range

with

hole_flg = ranks[1] << 4 | ranks[0]

It seems this is happening at the end of the emulator's job and the ranks list is empty. It is happening in both python 3.5 and python 2.7. Is the code given in the readme perhaps a little off and is using the emulator incorrectly or is the emulator not properly functioning?

Thanks!

Sometimes Illegal game state occurs in simulation

problem

  • 支払額の大きいプレイヤがfoldして,残ったプレイヤがpotのelligibleになっていないので,potの中身を受け取るプレイヤがいない
    • potのelligiblesのプレイヤがpay_info.status == foldedのみ
    • active_playersが空
    • 空の配列に対してmaxをとろうとしてクラッシュ

situation

  • あるプレイヤのstackが0になってる
  • そのプレイヤ?がfoldすると起きる

log

  [simulator] action, bet_amount = raise, 39
player=player1, action => raise:39
  [simulator] action, bet_amount = fold, 0
player=player2, action => fold:0
> /Users/kota/development/PyPokerEngine/pypokerengine/engine/game_evaluator.py(45)__find_winners_from()
-> best_score = max(score_with_players)[0]
(Pdb) l
 40     
 41         active_players = [player for player in players if player.is_active()]
 42         score_with_players = [(score_player(player), player) for player in active_players]
 43         if len(score_with_players) == 0:
 44           import pdb; pdb.set_trace()
 45  ->     best_score = max(score_with_players)[0]
 46         winners = [s_p[1] for s_p in score_with_players if s_p[0] == best_score]
 47         return winners
 48     
 49       @classmethod
 50       def __gen_hand_info_if_needed(self, players, community):
(Pdb) up
> /Users/kota/development/PyPokerEngine/pypokerengine/engine/game_evaluator.py(26)__calc_prize_distribution()
-> winners = self.__find_winners_from(community_card, pot["eligibles"])
(Pdb) l
 21       @classmethod
 22       def __calc_prize_distribution(self, community_card, players):
 23         prize_map = self.__create_prize_map(len(players))
 24         pots = self.create_pot(players)
 25         for pot in pots:
 26  ->       winners = self.__find_winners_from(community_card, pot["eligibles"])
 27           prize = pot["amount"] / len(winners)
 28           for winner in winners:
 29             prize_map[players.index(winner)] += prize
 30         return prize_map
 31     
(Pdb) [p.stack for p in players]
[116, 0]
(Pdb) [p.pay_info.status for p in players]
[0, 2]
(Pdb) [p.pay_info.amount for p in players]
[39, 45]

Impossible Hands

I have a Problem where impossible hands emerges. Example:
'TD', 'TH', '7D', 'TS', 'TD', 'TH'
You can see that 'TH' and 'TD' are double and this should be impossible.
Is there a setting to prevent this?

Option to suppress all prints

The constant stream of prints when running the poker game makes it very hard to track my own prints. A flag for the "setup_config" function would be nice, like
config = setup_config(max_round=10, initial_stack=100, small_blind_amount=5, show_game_messages=False)

Flush evaluation is wrong

I know this repo is not maintained, I still post this issue here in case anyone being confused about its behavior.

Issue

Here's what I encountered:

player [SixPlayer] gets hole card ['D5', 'HA'], current stack 100
player [G7Player] gets hole card ['CQ', 'D7'], current stack 100

Street "river" started. (community card = ['DQ', 'DJ', 'D9', 'CK', 'D6'])
"['SixPlayer']" won the round 1 (stack = {'SixPlayer': 720, 'G9Player': 0, 'G5Player': 0, 'HonestPlayer': 100, 'OurPlayer': 0, 'MyPokerPlayer': 0, 'RitzPlayer': 0, 'G3Player': 80, 'G7Player': 0})

Apparently, G7 shall win the game, because it has FLUSH with "D7", but SixPlayer has FLUSH with "D5". The result is wrong.

Root cause

See here:

def __calc_hand_info_flg(self, hole, community):

The flush can not be simply represented with only the max_rank_card. In fact, we need to compare these cards one by one.

In the issue we encountered, the flush was wrongly judged as the same for both G6 and G7, and then went to the 2nd bug (mentioned here), comparing the hole card, which results in G6 as the winner.

How to fix

We have to change how the "score" is represented for FLUSH. It shall contain 5 cards, instead of only 2.

# [Bit flg of hand][rank1(4bit)][rank2(4bit)]
# shall be:
# [Bit flg of hand][rank1(4bit)][rank2(4bit)][rank3(4bit)][rank4(4bit)][rank5(4bit)]

Add start_poker script as entry point in setup.py

Enable start_poker command after pip install PyPokerEngine

ex. virtualenv

Kota-no-MacBook-Air:~ kota$pip install virtualenv
Kota-no-MacBook-Air:~ kota$ virtualenv  // <-virtualenv executable script is added on PATH
You must provide a DEST_DIR
Usage: virtualenv [OPTIONS] DEST_DIR

Options:
...

HOW TO DO

Add script/start_pokerpath asentry_points in setup.py

Straight with A,2,3,4,5 don't work

I work right now on a solution for my other problem and found this issue in your code too.

Wright me if you want to see my solution. I can come with a full solution for the hand evaluator ;)

Improve usability

Update usability for reinforcement learning usecase.
Release version would be 0.1.x

  • Change module name from interface to api
  • Add Emulator class in api module
  • Provide method to play poker game as api
  • Add utility method to estimate hole card strength by random simulation
  • Update README

Release stable version

TODO list

  • document
    • [ ] add doc comment
    • create documet site with mkdocs
  • support python 3
  • [ ] refactoring
    • use game_state_utils in engine module

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.