diff --git a/CMakeLists.txt b/CMakeLists.txt index 58656fa..6d94857 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -43,9 +43,11 @@ add_subdirectory(src/lib) # This controls whether or not we are building the python # binaries, and possibly the wheel file. # TODO: add a separate option for building the wheel vs. python -if(BUILD_PYTHON) +if(BUILD_PYTHON OR BUILD_WHEEL) add_subdirectory(src/lib/python) -else() +endif() + +if(NOT BUILD_WHEEL) # none of these are needed in the wheel file add_subdirectory(src/programs) add_subdirectory(src/ext/googletest) diff --git a/README.md b/README.md index 825a13b..fb01c42 100644 --- a/README.md +++ b/README.md @@ -178,9 +178,8 @@ There is also a `pyproject.toml` file which can be used to create an installable wheel for the pythong package. The commands below can be used to build/install/verify the package. - pipx run build - python3 -m venv venv && . venv/bin/activate - pip install dist/pokerstove-*.whl + git clean -fxd && pipx run build + python3 -m venv venv && . venv/bin/activate && pip install dist/pokerstove-*.whl python src/lib/python/test-python deactivate diff --git a/pyproject.toml b/pyproject.toml index 697f8ba..2a36107 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -14,5 +14,5 @@ build.targets = ["pokerstove"] install.components = ["python"] sdist.exclude = ["src/programs", "android", "win32", "src/ext", "doc", ".*"] [tool.scikit-build.cmake.define] -BUILD_PYTHON = "ON" +BUILD_WHEEL = "ON" diff --git a/src/lib/pokerstove/peval/OmahaEightHandEvaluator.h b/src/lib/pokerstove/peval/OmahaEightHandEvaluator.h index a5c8e39..5008e4c 100644 --- a/src/lib/pokerstove/peval/OmahaEightHandEvaluator.h +++ b/src/lib/pokerstove/peval/OmahaEightHandEvaluator.h @@ -1,6 +1,5 @@ /** * Copyright (c) 2012 Andrew Prock. All rights reserved. - * $Id: OmahaEightHandEvaluator.h 2649 2012-06-30 04:53:24Z prock $ */ #ifndef PEVAL_OMAHAEIGHTHANDEVALUATOR_H_ #define PEVAL_OMAHAEIGHTHANDEVALUATOR_H_ @@ -69,22 +68,27 @@ class OmahaEightHandEvaluator : public PokerHandEvaluator // generate the possible sub hands, player hand candidates are all // 4c2 combinations of hands cards, // board candidates are all Nc3 board candidates, where N is the size - // of the board + // of the board. + // If we have 0 cards, that is one case (no board). The case of 1 and + // two card boards is also supported for various test cases and outliers. double combos = choose(board.size(), 3); + if (combos == 0) combos = 1; + std::vector board_candidates(static_cast(combos)); std::vector hand_candidates(6); fillHands(hand_candidates, hand); fillBoards(board_candidates, board); for (size_t i = 0; i < hand_candidates.size(); i++) + { for (size_t j = 0; j < board_candidates.size(); j++) { PokerEvaluation e = - CardSet(hand_candidates[i] | board_candidates[j]) - .evaluateHigh(); + CardSet(hand_candidates[i] | board_candidates[j]).evaluateHigh(); if (e > eval[0]) eval[0] = e; } + } // evaluate the low using brec's technique, see: // http://groups.google.com/group/rec.gambling.poker/msg/e8a3a7698d51f04a?dmode=source @@ -202,7 +206,21 @@ class OmahaEightHandEvaluator : public PokerHandEvaluator // fall through case 3: - candidates[0] = (clist[0] | clist[1] | clist[2]); + candidates[0] = clist[0] | clist[1] | clist[2]; + break; + + case 2: + candidates[0] = clist[0] | clist[1]; + break; + + case 1: + candidates[0] = clist[0]; + break; + + case 0: + candidates[0] = CardSet(); + break; + } } diff --git a/src/lib/pokerstove/peval/OmahaEightHandEvaluator.test.cpp b/src/lib/pokerstove/peval/OmahaEightHandEvaluator.test.cpp index b6f4061..ae53577 100644 --- a/src/lib/pokerstove/peval/OmahaEightHandEvaluator.test.cpp +++ b/src/lib/pokerstove/peval/OmahaEightHandEvaluator.test.cpp @@ -12,6 +12,42 @@ TEST(OmahaEightHandEvaluator, Construct) EXPECT_EQ(5, eval.boardSize()); } +TEST(OmahaEightHandEvaluator, NoBoard) +{ + OmahaEightHandEvaluator oeval; + // KQ high and 44, with no low + CardSet c1("2c3cKhQd"); + CardSet c2("4c5c4hTc"); + CardSet board; + + int KQbits = 0x01 << Rank::rank_code('K') | 0x01 << Rank::rank_code('Q'); + EXPECT_EQ(0, oeval.evaluateHand(c1, board).low().code()); + EXPECT_EQ(NO_PAIR, oeval.evaluateHand(c1, board).eval().type()); + EXPECT_EQ(KQbits, oeval.evaluateHand(c1, board).eval().kickerBits()); + + EXPECT_EQ(0, oeval.evaluateHand(c2, board).low().code()); + EXPECT_EQ(ONE_PAIR, oeval.evaluateHand(c2, board).eval().type()); + EXPECT_EQ(Rank::Four(), oeval.evaluateHand(c2, board).eval().majorRank()); +} + +TEST(OmahaEightHandEvaluator, OneCardBoard) +{ + OmahaEightHandEvaluator oeval; + // KQ high and 44, with no low + CardSet c1("2c3cKhQd"); + CardSet c2("4c5c4hTc"); + CardSet board("Ks"); + + int KQbits = 0x01 << Rank::rank_code('K') | 0x01 << Rank::rank_code('Q'); + EXPECT_EQ(0, oeval.evaluateHand(c1, board).low().code()); + EXPECT_EQ(ONE_PAIR, oeval.evaluateHand(c1, board).eval().type()); + EXPECT_EQ(Rank::King(), oeval.evaluateHand(c1, board).eval().majorRank()); + + EXPECT_EQ(0, oeval.evaluateHand(c2, board).low().code()); + EXPECT_EQ(ONE_PAIR, oeval.evaluateHand(c2, board).eval().type()); + EXPECT_EQ(Rank::Four(), oeval.evaluateHand(c2, board).eval().majorRank()); +} + TEST(OmahaEightHandEvaluator, SplitPot) { OmahaEightHandEvaluator eval; diff --git a/src/lib/pokerstove/peval/PokerHandEvaluation.h b/src/lib/pokerstove/peval/PokerHandEvaluation.h index 076c675..54e5997 100644 --- a/src/lib/pokerstove/peval/PokerHandEvaluation.h +++ b/src/lib/pokerstove/peval/PokerHandEvaluation.h @@ -7,6 +7,7 @@ #include #include +#include #include "PokerEvaluation.h" /** @@ -60,6 +61,20 @@ namespace pokerstove return eval2 != PokerEvaluation(); } + int size() const + { + return highlow() ? 2 : 1; + } + + std::vector evals() const + { + std::vector evals; + evals.push_back(eval1); + if (highlow()) + evals.push_back(eval2); + return evals; + } + bool empty() const { return (eval1 == PokerEvaluation(0)); diff --git a/src/lib/python/pokerstove.i b/src/lib/python/pokerstove.i index 9722763..90d9a6a 100644 --- a/src/lib/python/pokerstove.i +++ b/src/lib/python/pokerstove.i @@ -2,6 +2,7 @@ %include %include +%include // NOTE: game evaluators are available through the // PokerHandEvaluator factory @@ -31,6 +32,9 @@ #include "pokerstove/penum/CardDistribution.h" %} +%template(CardVector) std::vector; +%template(PokerEvaluationVector) std::vector; + // take care of some shared pointer issues %include %shared_ptr(pokerstove::PokerHandEvaluator) diff --git a/src/lib/python/test-python b/src/lib/python/test-python index 37f9a5c..b8b4cd0 100755 --- a/src/lib/python/test-python +++ b/src/lib/python/test-python @@ -51,6 +51,8 @@ ph3 = PokerHand('acAd3c4s5h6d7c') print('ph1: ', ph1) print('ph2: ', ph2) print('ph3: ', ph3) +cards = ph3.cards() +print('card list: ', len(cards), cards) print('-- holdem hand evaluation --') v = PokerHandEvaluator.alloc('h') @@ -59,6 +61,19 @@ e5 = v.evaluateHand(cs4, cs5) print(e4) print(e5) +print('-- omaha hand evaluation --') +cs6 = CardSet('AcAd2sKc') +brd = CardSet('4c5h8c9dJs') +v = PokerHandEvaluator.alloc('o8') +e6 = v.evaluateHand(cs6, brd) +print(e6) +evals = e6.evals() +print('number of evals: ', e6.size()) +print('length of evals: ', len(evals)) +print('actual evals: ', evals) +e7 = v.evaluateHand(cs6) +print('omaha, no board: ', e7.evals()) + print('-- holdem facts --') print('holdem board size: ', BOARD_SIZE) print('num holdem rounds: ', NUM_HOLDEM_ROUNDS)