diff --git a/packaging/windows/py2exe_setup.py b/packaging/windows/py2exe_setup.py index 0f46f8db..84b75886 100644 --- a/packaging/windows/py2exe_setup.py +++ b/packaging/windows/py2exe_setup.py @@ -68,7 +68,6 @@ import matplotlib import shutil #from datetime import date - def isSystemDLL(pathname): #dwmapi appears to be vista-specific file, not XP if os.path.basename(pathname).lower() in ("dwmapi.dll"): @@ -120,6 +119,7 @@ pydir = rootdir+'pyfpdb/' gfxdir = rootdir+'gfx/' sys.path.append( pydir ) # allows fpdb modules to be found by options/includes below + print "\n" + r"Output will be created in "+distdir print "*** Cleaning working folders ***" @@ -142,6 +142,9 @@ setup( {'script': pydir+'Configuration.py', } ], + console = [ {'script': pydir+'Stove.py', } + ], + options = {'py2exe': { 'packages' : ['encodings', 'matplotlib'], 'includes' : ['gio', 'cairo', 'pango', 'pangocairo', 'atk', 'gobject' diff --git a/packaging/windows/pypoker138walkthrough.txt b/packaging/windows/pypoker138walkthrough.txt index 6a4ab8f7..1c7ee0f4 100644 --- a/packaging/windows/pypoker138walkthrough.txt +++ b/packaging/windows/pypoker138walkthrough.txt @@ -1,177 +1,191 @@ -pypokereval build for windows stepbystep guide ----------------------------------------------- - -Created by Gimick on 3rd December 2010 - -This walkthrough is derived with the assistance of EricBlade and the build notes -supplied by Loic Dachary http://dachary.org/ - -Content is available under the the GNU Affero General Public License version 3 - - -0. Build environ ----------------- - -We are building against the 2008 runtime because Python 2.6 - has the same dependency (msvcr90.dll version 9.0.21022.8) - -Using winXPhome 32 bit - -1 Visual studio ---------------- - -1.1/ Get the ISO CD from here ... http://www.microsoft.com/express/Downloads/#2008-All - -1.2/ Run and install Visual C++ only, don't bother with the additional packages offered - -This package will run 30 days before registration is needed - -2. Python runtime ------------------ - -2.1/ Install python runtime from here ... - -Python 2.6.5 ... http://www.python.org/ftp/python/2.6.5/python-2.6.5.msi - -3. Source install ------------------ - -3.1/ grab sources from here - -pypoker-eval v138 ... http://download.gna.org/pokersource/sources/pypoker-eval-138.0.tar.gz -poker-eval v138 ... http://download.gna.org/pokersource/sources/poker-eval-138.0.tar.gz - -3.2/ unpack and place the pypoker-eval-138 directory in c:\ -3.2.1/ rename to pypoker-eval - -3.3/ unpack and place the poker-eval-138 directory in c:\ -3.3.1/ rename to poker-eval - -Important: the build will fail with bizarre missing header files if the project is placed - in a directory containing a space character - you have been warned! - -4. Update source file ---------------------- - -4.1/ dos> write c:/pypoker-eval/pypokereval.c - -change this: - -#define VERSION_NAME(W) W##2_4 -#define PYTHON_VERSION "2_4" - -to be this: - -#define VERSION_NAME(W) W##2_6 -#define PYTHON_VERSION "2_6" - -4.2/ save and exit - -5. Build pre-preparation ------------------------- - -(Here we are converting the two project definition files to 2008) - -5.1 navigate to directory c:/poker-eval -5.1.1 double click poker-eval.vcproj -5.1.2 Visual studio will launch and make a conversion - accept all defaults -5.1.3 exit and save - -5.2 navigate to directory c:/pypoker-eval -5.2.1 double click pypoker-eval.vcproj -5.2.2 Visual studio will launch and make a conversion - accept all defaults -5.2.3 exit - -6. build preparation --------------------- - -6.2 navigate to directory c:/pypoker-eval -6.2.1 double click pypoker-eval.vcproj - visual studio should launch - -6.2.3 Select Build...configuration manager... - Select "active solution configuration" to "Release" - (The configuration for both projects will change to "Release") - -6.2.3 Close the configuration manager - -6.2.4 In the solution explorer window, hilight pythonpoker-eval / right mouse / properties... - -6.2.5 In the pythonpoker-eval properties dialog, - -change references to "python24" to "python26" in the following: - - = C/C++/Additional Include Directories/ - = linker/general/Additional library directories - = linker/input/Additional Dependencies - -Change the following - - = linker/generate debug info - set to No - = linker/debugging/Generate debug info - set to No - -6.2.6 Apply all changes to the properties dialog and close - -6.3 Exit from visual studio - -7. Build poker eval -------------------- - -7.1 navigate to directory c:/poker-eval -7.1.1 double click poker-eval.vcproj -7.1.2 Visual studio will launch - -7.2 In the solution explorer window, hilight poker-eval / right mouse / build - -7.3 There should be no errors - -7.4 Exit from visual studio - - -8. Build pypoker eval ---------------------- - -8.1 navigate to directory c:/pypoker-eval -8.1.1 double click pypoker-eval.vcproj -8.1.2 Visual studio will launch - -8.2 In the solution explorer window, hilight pythonpoker-eval / right mouse / build - -8.3 There should be no errors (but a few warnings) - -8.4 Exit from visual studio - -9. packaging ------------- - -9.1 Navigate to c:/pypoker-eval/release -9.2 the output file is pypokereval.dll -9.3 rename this file to _pokereval_2_6.pyd - -9.4 create a zip file containing : - -_pokereval_2_6.pyd from releases -test.py from pypoker-eval-138.0 -pokereval.py from pypoker-eval-138.0 -poker-eval.vcproj from c:\poker-eval -pypoker-eval.vcproj from c:\pypoker-eval -pypokereval.c from c:\pypoker-eval - -Remember to include the version (138), python 265 and win32 in the package filename - -10. Installation and Testing ----------------------------- - -Python 2.6.5 must be installed - -10.1 Extract this package to directory -10.2 Change directory to the directory in 10.1 -10.3 execute dos> c:\Python26\python.exe test.py -10.4 hand-output should scroll down the screen -10.5 start the python interpreter -10.6 >>> import pokereval -10.7 No errors should be seen - - - - - +pypokereval build for windows stepbystep guide +---------------------------------------------- + +Created by Gimick on 3rd December 2010 + +This walkthrough is derived with the assistance of EricBlade and the build notes +supplied by Loic Dachary http://dachary.org/ + +Content is available under the the GNU Affero General Public License version 3 + + +0. Build environ +---------------- + +We are building against the 2008 runtime because Python 2.6 + has the same dependency (msvcr90.dll version 9.0.21022.8) + +Using winXPhome 32 bit + +1 Visual studio +--------------- + +1.1/ Get the ISO CD from here ... http://www.microsoft.com/express/Downloads/#2008-All + +1.2/ Run and install Visual C++ only, don't bother with the additional packages offered + +This package will run 30 days before registration is needed + +2. Python runtime +----------------- + +2.1/ Install python runtime from here ... + +Python 2.6.5 ... http://www.python.org/ftp/python/2.6.5/python-2.6.5.msi + +3. Source install +----------------- + +3.1/ grab sources from here + +pypoker-eval v138 ... http://download.gna.org/pokersource/sources/pypoker-eval-138.0.tar.gz +poker-eval v138 ... http://download.gna.org/pokersource/sources/poker-eval-138.0.tar.gz + +3.2/ unpack and place the pypoker-eval-138 directory in c:\ +3.2.1/ rename to pypoker-eval + +3.3/ unpack and place the poker-eval-138 directory in c:\ +3.3.1/ rename to poker-eval + +Important: the build will fail with bizarre missing header files if the project is placed + in a directory containing a space character - you have been warned! + +4. Update source file +--------------------- + +4.1/ dos> write c:/pypoker-eval/pypokereval.c + +change this: + +#define VERSION_NAME(W) W##2_4 +#define PYTHON_VERSION "2_4" + +to be this: + +#define VERSION_NAME(W) W##2_6 +#define PYTHON_VERSION "2_6" + +4.2/ save and exit + +4.3/ dos> write c:/pypoker-eval/pokereval.py + +Comment-out this line: + +_pokereval = __import__('_pokereval_' + sys.version[0] + '_' + sys.version[2]) + +Insert this one in its' place: + +import _pokereval_2_6 as _pokereval + + +4.4/ save and exit + + +5. Build pre-preparation +------------------------ + +(Here we are converting the two project definition files to 2008) + +5.1 navigate to directory c:/poker-eval +5.1.1 double click poker-eval.vcproj +5.1.2 Visual studio will launch and make a conversion - accept all defaults +5.1.3 exit and save + +5.2 navigate to directory c:/pypoker-eval +5.2.1 double click pypoker-eval.vcproj +5.2.2 Visual studio will launch and make a conversion - accept all defaults +5.2.3 exit + +6. build preparation +-------------------- + +6.2 navigate to directory c:/pypoker-eval +6.2.1 double click pypoker-eval.vcproj - visual studio should launch + +6.2.3 Select Build...configuration manager... + Select "active solution configuration" to "Release" + (The configuration for both projects will change to "Release") + +6.2.3 Close the configuration manager + +6.2.4 In the solution explorer window, hilight pythonpoker-eval / right mouse / properties... + +6.2.5 In the pythonpoker-eval properties dialog, + +change references to "python24" to "python26" in the following: + + = C/C++/Additional Include Directories/ + = linker/general/Additional library directories + = linker/input/Additional Dependencies + +Change the following + + = linker/generate debug info - set to No + = linker/debugging/Generate debug info - set to No + +6.2.6 Apply all changes to the properties dialog and close + +6.3 Exit from visual studio + +7. Build poker eval +------------------- + +7.1 navigate to directory c:/poker-eval +7.1.1 double click poker-eval.vcproj +7.1.2 Visual studio will launch + +7.2 In the solution explorer window, hilight poker-eval / right mouse / build + +7.3 There should be no errors + +7.4 Exit from visual studio + + +8. Build pypoker eval +--------------------- + +8.1 navigate to directory c:/pypoker-eval +8.1.1 double click pypoker-eval.vcproj +8.1.2 Visual studio will launch + +8.2 In the solution explorer window, hilight pythonpoker-eval / right mouse / build + +8.3 There should be no errors (but a few warnings) + +8.4 Exit from visual studio + +9. packaging +------------ + +9.1 Navigate to c:/pypoker-eval/release +9.2 the output file is pypokereval.dll +9.3 rename this file to _pokereval_2_6.pyd + +9.4 create a zip file containing : + +_pokereval_2_6.pyd from releases +test.py from pypoker-eval-138.0 +pokereval.py from pypoker-eval-138.0 +poker-eval.vcproj from c:\poker-eval +pypoker-eval.vcproj from c:\pypoker-eval +pypokereval.c from c:\pypoker-eval + +Remember to include the version (138), python 265 and win32 in the package filename + +10. Installation and Testing +---------------------------- + +Python 2.6.5 must be installed + +10.1 Extract this package to directory +10.2 Change directory to the directory in 10.1 +10.3 execute dos> c:\Python26\python.exe test.py +10.4 hand-output should scroll down the screen +10.5 start the python interpreter +10.6 >>> import pokereval +10.7 No errors should be seen + + + + + diff --git a/pyfpdb/_pokereval_2_6.pyd b/pyfpdb/_pokereval_2_6.pyd new file mode 100644 index 00000000..f11d3081 Binary files /dev/null and b/pyfpdb/_pokereval_2_6.pyd differ diff --git a/pyfpdb/pokereval.py b/pyfpdb/pokereval.py new file mode 100644 index 00000000..08d08786 --- /dev/null +++ b/pyfpdb/pokereval.py @@ -0,0 +1,338 @@ +# +# Copyright (C) 2007, 2008 Loic Dachary +# Copyright (C) 2004, 2005, 2006 Mekensleep +# +# Mekensleep +# 24 rue vieille du temple +# 75004 Paris +# licensing@mekensleep.com +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. +# +# Authors: +# Loic Dachary +# +# +import sys + +# for fpdb alter the following line from __import__ to import...as... . +# fpdb py2exe package build does no recognise __import__ statement, +# and fails at runtime with _pokereval_2_6 not found + +#_pokereval = __import__('_pokereval_' + sys.version[0] + '_' + sys.version[2]) +import _pokereval_2_6 as _pokereval + +from types import * + +class PokerEval: + """\ +Evaluate the strengh of a poker hand for a given poker variant. +In all methods, when a list of cards is to be provided (for instance +with the "hand" argument of the "best" method), each member of the +list may be a number or a string designating a card according to +the following table: + + 2h/00 2d/13 2c/26 2s/39 + 3h/01 3d/14 3c/27 3s/40 + 4h/02 4d/15 4c/28 4s/41 + 5h/03 5d/16 5c/29 5s/42 + 6h/04 6d/17 6c/30 6s/43 + 7h/05 7d/18 7c/31 7s/44 + 8h/06 8d/19 8c/32 8s/45 + 9h/07 9d/20 9c/33 9s/46 + Th/08 Td/21 Tc/34 Ts/47 + Jh/09 Jd/22 Jc/35 Js/48 + Qh/10 Qd/23 Qc/36 Qs/49 + Kh/11 Kd/24 Kc/37 Ks/50 + Ah/12 Ad/25 Ac/38 As/51 + +The string __ (two underscore) or the number 255 are placeholders +meaning that the card is unknown. +""" + + def best(self, side, hand, board = []): + """\ +Return the best five card combination that can be made with the cards +listed in "hand" and, optionally, board. The "side" may be "hi" or +"low". The "board" argument must only be provided for variants where +knowing if a given card is taken from the board or not is significant +(such as Omaha but not Holdem). + +A list is returned. The first element is the numerical value +of the hand (better hands have higher values if "side" is "hi" and +lower values if "side" is "low"). The second element is a list whose +first element is the strength of the hand among the following: + +Nothing (only if "side" equals "low") +NoPair +TwoPair +Trips +Straight +Flush +FlHouse +Quads +StFlush + +The last five elements are numbers describing the best hand properly +sorted (for instance the ace is at the end for no pair if "side" is low or +at the beginning if "side" high). + +Examples: + +[134414336, ['StFlush', 29, 28, 27, 26, 38]] is the wheel five to ace, clubs +[475920, ['NoPair', 45, 29, 41, 39, 51]] is As, 8s, 5c, 4s, 2s +[268435455, ['Nothing']] means there is no qualifying low +""" + if len(hand + board) >= 5: + return _pokereval.eval_hand(side, hand, board) + else: + return False + + def best_hand(self, side, hand, board = []): + """\ +Return the best five card combination that can be made with the cards +listed in "hand" and, optionaly, board. The "side" may be "hi" or +"low". The returned value is the second element of the list returned +by the "best" method. +""" + if len(hand + board) >= 5: + return _pokereval.eval_hand(side, hand, board)[1] + else: + return False + + def best_hand_value(self, side, hand, board = []): + """\ +Return the best five card combination that can be made with the cards +listed in "hand" and, optionaly, board. The "side" may be "hi" or +"low". The returned value is the first element of the list returned +by the "best" method. +""" + if len(hand + board) >= 5: + return _pokereval.eval_hand(side, hand, board)[0] + else: + return False + + def evaln(self, cards): + """\ +Call the poker-eval Hand_EVAL_N function with the "cards" argument. +Return the strength of the "cards" as a number. The higher the +better. +""" + return _pokereval.evaln(cards) + + def winners(self, *args, **kwargs): + """\ +Return a list of the indexes of the best hands, relative to the "pockets" +keyword argument. For instance, if the first pocket and third pocket cards +tie, the list would be [0, 2]. Since there may be more than one way to +win a hand, a hash is returned with the list of the winners for each so +called side. For instace {'hi': [0], 'low': [1]} means pocket cards +at index 0 won the high side of the hand and pocket cards at index 1 +won the low side. + +See the"poker_eval" method for a detailed +explanation of the semantics of the arguments. + +If the keyword argument "fill_pockets" is set, pocket cards +can contain a placeholder (i.e. 255 or __) that will be be +used as specified in the "poker_eval" method documentation. + +If the keyword argument "fill_pockets" is not set, pocket cards +that contain at least one placeholder (i.e. 255 or __) are +ignored completly. For instance if winners is called as follows +o.winners(game = 'holdem', pockets = [ [ '__', 'As' ], [ 'Ks', 'Kd'] ]) +it is strictly equivalent as calling +o.winners(game = 'holdem', pockets = [ [ 'Ks', 'Kd'] ]). +""" + index2index = {} + normalized_pockets = [] + normalized_index = 0 + pockets = kwargs["pockets"][:] + for index in xrange(len(pockets)): + if not kwargs.has_key("fill_pockets"): + if 255 in pockets[index] or "__" in pockets[index]: + pockets[index] = [] + + if pockets[index] != []: + normalized_pockets.append(pockets[index]) + index2index[index] = normalized_index + normalized_index += 1 + kwargs["pockets"] = normalized_pockets + + results = _pokereval.poker_eval(*args, **kwargs) + + (count, haslopot, hashipot) = results.pop(0) + winners = { 'low': [], 'hi': [] } + for index in xrange(len(pockets)): + if index2index.has_key(index): + result = results[index2index[index]] + if result[1] == 1 or result[3] == 1: + winners["hi"].append(index) + if result[4] == 1 or result[6] == 1: + winners["low"].append(index) + + if not haslopot or len(winners["low"]) == 0: + del winners["low"] + if not hashipot: + del winners["hi"] + return winners + + def poker_eval(self, *args, **kwargs): + """\ +Provided with a description of a poker game, return the outcome (if at showdown) or +the expected value of each hand. The poker game description is provided as a set +of keyword arguments with the following meaning: + +game : the variant (holdem, holdem8, omaha, omaha8, 7stud, 7stud8, razz, + 5draw, 5draw8, 5drawnsq, lowball, lowball27). + Mandatory, no default. + +pockets : list of pocket cards for each player still in game. Each member + of the list is a list of cards. The position of the pocket cards + in the list is meaningfull for the value returned will refer to + this position when stating which player wins, tie or loose. + Example: [ ["tc", "ac"], ["3h", "ah"], ["8c", "6h"]] + Cards do not have to be real cards like "tc" or "4s". They may also be a + placeholder, denoted by "__" or 255. When using placeholders, the + keyword argument "iterations" may be specified to use Monte Carlo instead of + exhaustive exploration of all the possible combinations. + Example2: [ ["tc", "__"], [255, "ah"], ["8c", "6h"]] + + Mandatory, no default. + +board : list of community cards, for games where this is meaningfull. If + specified when irrelevant, the return value cannot be predicted. + Default: [] + +dead : list of dead cards. These cards won't be accounted for when exloring + the possible hands. + Default: [] + +iterations: the maximum number of iterations when exploring the + possible outcome of a given hand. Roughly speaking, each + iteration means to distribute cards that are missing (for + which there are place holders in the board or pockets + keywords arguments, i.e. 255 or __). If the number of + iterations is not specified and there are place holders, + the return value cannot be predicted. + Default: +infinite (i.e. exhaustive exploration) + +Example: object.poker_eval(game = "holdem", + pockets = [ ["tc", "ac"], ["3h", "ah"], ["8c", "6h"]], + dead = [], + board = ["7h", "3s", "2c"]) + +The return value is a map of two entries: +'info' contains three integers: + - the number of samples (which must be equal to the number of iterations given + in argument). + - 1 if the game has a low side, 0 otherwise + - 1 if the game has a high side, 0 otherwise +'eval' is a list of as many maps as there are pocket cards, each +made of the following entries: + 'scoop': the number of time these pocket cards scoop + 'winhi': the number of time these pocket cards win the high side + 'losehi': the number of time these pocket cards lose the high side + 'tiehi': the number of time these pocket cards tie for the high side + 'winlo': the number of time these pocket cards win the low side + 'loselo': the number of time these pocket cards lose the low side + 'tielo': the number of time these pocket cards tie for the low side + 'ev': the EV of these pocket cards as an int in the range [0,1000] with + 1000 being the best. + +It should be clear that if there is only one sample (i.e. because all the +cards are known which is the situation that occurs at showdown) the details +provided by the 'eval' entry is mostly irrelevant and the caller might +prefer to call the winners method instead. +""" + result = _pokereval.poker_eval(*args, **kwargs) + return { + 'info': result[0], + 'eval': [ { 'scoop': x[0], + 'winhi': x[1], + 'losehi': x[2], + 'tiehi': x[3], + 'winlo': x[4], + 'loselo': x[5], + 'tielo': x[6], + 'ev': int(x[7] * 1000) } for x in result[1:] ] + } + + def deck(self): + """\ +Return the list of all cards in the deck. +""" + return [ self.string2card(i + j) for i in "23456789TJQKA" for j in "hdcs" ] + + def nocard(self): + """Return 255, the numerical value of a place holder in a list of cards.""" + return 255 + + def string2card(self, cards): + """\ +Convert card names (strings) to card numbers (integers) according to the +following map: + + 2h/00 2d/13 2c/26 2s/39 + 3h/01 3d/14 3c/27 3s/40 + 4h/02 4d/15 4c/28 4s/41 + 5h/03 5d/16 5c/29 5s/42 + 6h/04 6d/17 6c/30 6s/43 + 7h/05 7d/18 7c/31 7s/44 + 8h/06 8d/19 8c/32 8s/45 + 9h/07 9d/20 9c/33 9s/46 + Th/08 Td/21 Tc/34 Ts/47 + Jh/09 Jd/22 Jc/35 Js/48 + Qh/10 Qd/23 Qc/36 Qs/49 + Kh/11 Kd/24 Kc/37 Ks/50 + Ah/12 Ad/25 Ac/38 As/51 + +The "cards" argument may be either a list in which case a converted list +is returned or a string in which case the corresponding number is +returned. +""" + if type(cards) is ListType or type(cards) is TupleType: + return [ _pokereval.string2card(card) for card in cards ] + else: + return _pokereval.string2card(cards) + + def card2string(self, cards): + """\ +Convert card numbers (integers) to card names (strings) according to the +following map: + + 2h/00 2d/13 2c/26 2s/39 + 3h/01 3d/14 3c/27 3s/40 + 4h/02 4d/15 4c/28 4s/41 + 5h/03 5d/16 5c/29 5s/42 + 6h/04 6d/17 6c/30 6s/43 + 7h/05 7d/18 7c/31 7s/44 + 8h/06 8d/19 8c/32 8s/45 + 9h/07 9d/20 9c/33 9s/46 + Th/08 Td/21 Tc/34 Ts/47 + Jh/09 Jd/22 Jc/35 Js/48 + Qh/10 Qd/23 Qc/36 Qs/49 + Kh/11 Kd/24 Kc/37 Ks/50 + Ah/12 Ad/25 Ac/38 As/51 + +The "cards" argument may be either a list in which case a converted list +is returned or an integer in which case the corresponding string is +returned. +""" + if type(cards) is ListType or type(cards) is TupleType: + return [ _pokereval.card2string(card) for card in cards ] + else: + return _pokereval.card2string(cards) +