Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Error Calculating Hand Strength for OmahaEightOrBetterLowHand #18

Open
pauldalewilliams opened this issue Oct 26, 2024 · 3 comments
Open

Comments

@pauldalewilliams
Copy link

pauldalewilliams commented Oct 26, 2024

I was trying to use this to calculate Omaha High Low hand strengths but I think I ran into a bug:

import pokerkit as pk

pk.calculate_hand_strength(
    3,
    pk.parse_range('AsAd3d2s'),
    pk.Card.parse('4s8c3s'),
    4,
    5,
    pk.Deck.STANDARD,
    (pk.hands.OmahaEightOrBetterLowHand,),
    sample_count=700,
)

results in this error:

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "C:\Users\pdw\code\bp\Lib\site-packages\pokerkit\analysis.py", line 403, in calculate_hand_strength
    equities = calculate_equities(
               ^^^^^^^^^^^^^^^^^^^
  File "C:\Users\pdw\code\bp\Lib\site-packages\pokerkit\analysis.py", line 324, in calculate_equities
    for i, equity in chain.from_iterable(map(enumerate, mapper(fn, indices))):
                     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\Users\pdw\code\bp\Lib\site-packages\pokerkit\analysis.py", line 208, in __calculate_equities_1
    return __calculate_equities_0(
           ^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\Users\pdw\code\bp\Lib\site-packages\pokerkit\analysis.py", line 182, in __calculate_equities_0
    hands = list(
            ^^^^^
  File "C:\Users\pdw\code\bp\Lib\site-packages\pokerkit\hands.py", line 542, in from_game
    raise ValueError(
ValueError: No valid ABCMeta hand can be formed from the hole and board cards.

It seems like the evaluation for low hands isn't properly calculating the "max_hand" as best as I can tell from digging in the code. But I have no idea what to test next - none of my attempts to fix it have worked so far. Any suggestions or am I just doing something wrong?

It works great for OmahaHoldemHand, so thank you for that!

@pauldalewilliams pauldalewilliams changed the title Calculate Hand Strenght for OmahaEightOrBetterLowHand Calculate Hand Strength for OmahaEightOrBetterLowHand Oct 26, 2024
@pauldalewilliams pauldalewilliams changed the title Calculate Hand Strength for OmahaEightOrBetterLowHand Error Calculating Hand Strength for OmahaEightOrBetterLowHand Oct 26, 2024
@pauldalewilliams
Copy link
Author

Ah, I think I'm on to something - the problem may be with what happens when the random hands generated can't create a valid low hand:

pk.calculate_equities(
    (pk.parse_range('3d2sAsAd'),
     pk.parse_range('5dJcQcKd'),
    ),
    pk.Card.parse('8c4s3s'),
    4,
    5,
    pk.Deck.STANDARD,
    (pk.hands.OmahaEightOrBetterLowHand,),
    sample_count=700,
)

fails but this one works:

pk.calculate_equities(
    (pk.parse_range('3d2sAsAd'),
     pk.parse_range('5d3cAcKd'),
    ),
    pk.Card.parse('8c4s3s'),
    4,
    5,
    pk.Deck.STANDARD,
    (pk.hands.OmahaEightOrBetterLowHand,),
    sample_count=700,
)

This is the most direct route to triggering the error:

pk.OmahaEightOrBetterLowHand.from_game('5dJcQcKd','8c4s3s')

For my purposes, I managed to work around it by modifying hands.py BoardCombinationHand and HoleBoardCombinationHand to go from:

            except ValueError:
                pass
            else:
                if max_hand is None or hand > max_hand:
                    max_hand = hand

        if max_hand is None:
            raise ValueError(
                (
                    f'No valid {type(cls).__qualname__} hand can be formed'
                    ' from the hole and board cards.'
                ),
            )

        return max_hand

to this:

            except ValueError:
                pass
            else:
                #if max_hand is None or hand > max_hand:
                if hand is not None and (max_hand is None or hand > max_hand): # added by PDW
                    max_hand = hand

        #if max_hand is None:
        if max_hand is None and not cls.low: # added by PDW
            raise ValueError(
                (
                    f'No valid {type(cls).__qualname__} hand can be formed'
                    ' from the hole and board cards.'
                ),
            )

        return max_hand

I'm sure this isn't a valid permanent fix but I'm sharing what I found as the root cause - EightOrBetterLookup adds no entries for non-qualifying hands because it generates a ValueError it tries to create an instance of the Hand class and the init fails on the self.lookup.has_entry(self.cards) call on line 90 of hands.py.

@AussieSeaweed
Copy link
Member

Hi,

Sorry for the late response. Thanks for sharing this!

Also, I find the error message containing 'ABCMeta' to be problematic. It should be the actual hand class.

I will think of ways to fix this... I think the change can be isolated to pokerkit/analysis.py.

I don't have the bandwidth to work on this right now, but will aim to get this done by early November.

Thanks!

@pauldalewilliams
Copy link
Author

No worries! My fix is working for my purposes but I'm mainly using it for the equities/hand strength anyway, so I'm not worried about side effects (yet...). Thanks for your work on this!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants