Package: pokerlib
pokerlibA lightweight Python poker library, focusing on simplifying a Texas hold'em poker game implementation, when its io is supplied. It includes modules that help with hand parsing and poker game continuation.To install, runpipinstallpokerlibIf experiencing issues, specify the latest version aspipinstallpokerlib==2.2.6UsageLibrary consists of a module for parsing cards, which can be used separately, and modules that aid in running a poker game.HandParserThis module takes care of hand parsing. A hand usually consists of 2 dealt cards plus 5 on the board, andHandParseris heavily optimized to work with up to 7 cards (with more than 7 cards, this is no longer Texas hold'em). A card is defined as a pair of two enums - Rank and Suit. All of the enums used are ofIntEnumtype, so you can also freely interchange them for integers. Below is an example of how to construct two different hands and then compare them.frompokerlibimportHandParserfrompokerlib.enumsimportRank,Suithand1=HandParser([(Rank.KING,Suit.SPADE),(Rank.ACE,Suit.SPADE)])hand2=HandParser([(Rank.NINE,Suit.SPADE),(Rank.TWO,Suit.CLUB)])board=[(Rank.EIGHT,Suit.SPADE),(Rank.TEN,Suit.SPADE),(Rank.JACK,Suit.SPADE),(Rank.QUEEN,Suit.SPADE),(Rank.TWO,Suit.HEART)]# add new cards to each handhand1+=board# add the board to hand1hand2+=board# add the board to hand2print(hand1.handenum)# Hand.STRAIGHTFLUSHprint(hand2.handenum)# Hand.STRAIGHTFLUSHprint(hand1>hand2)# Truenote:In the previous version, each hand had to be parsed manually withhand.parse(), now calling any of the methods requiring the hand to be parsed, triggers parsing automatically. This only happens once, except if the cards in a given hand change. The only way cards in a hand should change is through the__iadd__method. If this method is called with hand already parsed, the hand is considered unparsed.It is also possible to fetch hand's kickers.hand=HandParser([(Rank.TWO,Suit.DIAMOND),(Rank.ACE,Suit.CLUB),(Rank.TWO,Suit.SPADE),(Rank.THREE,Suit.DIAMOND),(Rank.TEN,Suit.HEART),(Rank.SIX,Suit.HEART),(Rank.KING,Suit.CLUB)])print(list(hand.kickercards))# [#   (<Rank.ACE: 12>, <Suit.CLUB: 1>),#   (<Rank.KING: 11>, <Suit.CLUB: 1>),#   (<Rank.TEN: 8>, <Suit.HEART: 3>)# ]Using HandParser, we canestimate the probabilityof a given hand winning the game with given known cards on the table (as implemented in another python cli-apphere). We do this by repeatedly random-sampling hands, then averaging the wins. Mathematically, this process converges to the probability by the law of large numbers.Poker GameA poker table can be established by providing its configuration.
A poker table object responds to given input with appropriate output,
which can be customized by overriding the two functions producing it.frompokerlibimportTable,Player,PlayerSeats# table that prints outputsclassMyTable(Table):defpublicOut(self,out_id,**kwargs):print(out_id,kwargs)defprivateOut(self,player_id,out_id,**kwargs):print(out_id,kwargs)# define a new tabletable=MyTable(table_id=0,seats=PlayerSeats([None]*9),buyin=100,small_blind=5,big_blind=10)We could have seated players on theseatsinsideMyTableconstructor,
but let's add them to the defined table.player1=Player(table_id=table.id,_id=1,name='alice',money=table.buyin)player2=Player(table_id=table.id,_id=2,name='bob',money=table.buyin)# seat player1 at the first seattable+=player1,0# seat player2 at the first free seattable+=player2Communication with thetableobject is established through specified enums,
which can be modified by overriding table'spublicInmethod.
Using enum IO identifiers, we can implement a poker game as shown below.frompokerlib.enumsimportRoundPublicInId,TablePublicInIdtable.publicIn(player1.id,TablePublicInId.STARTROUND)table.publicIn(player1.id,RoundPublicInId.CALL)table.publicIn(player2.id,RoundPublicInId.CHECK)table.publicIn(player1.id,RoundPublicInId.CHECK)table.publicIn(player2.id,RoundPublicInId.RAISE,raise_by=50)table.publicIn(player1.id,RoundPublicInId.CALL)table.publicIn(player1.id,RoundPublicInId.CHECK)table.publicIn(player2.id,RoundPublicInId.CHECK)table.publicIn(player1.id,RoundPublicInId.ALLIN)table.publicIn(player2.id,RoundPublicInId.CALL)Wrong inputs are mostly ignored, though they can produce a response, when it seems useful. As noted before, when providing input, thetableobject responds with output ids (e.g.PLAYERACTIONREQUIRED) along with additional data that depends on the output id. For all possible outputs, checkRoundPublicInIdandTablePublicInIdenums.A simple command line game, where you respond with enum names, can be implemented simply as inexamples/round_simulate.py. Commandpythonexamples/round_simulate.py3runs a poker game with 3 players using the terminal as IO. Note that responses are in non-formatted raw form.TestsBasic tests for this library are included. You can testHandParserby runningpythontests/handparser_reactive.pyandRoundwithpythontests/round_test.pyNote that HandParser can be fuzz tested against another poker librarypokerfacewithpythontests/handparser_against_pokerface.pywhich means it is considered safe. On the other hand,Tablemay still have some bugs.LicenseGNU General Public License v3.0