From ed2822d4c482b06079d8286d8a1460d6aa4944a9 Mon Sep 17 00:00:00 2001 From: Ken Date: Wed, 13 Jul 2016 10:00:26 +0900 Subject: [PATCH 01/28] Simplify rank method header declarations. --- src/FiveEval.h | 6 ++---- src/SevenEval.h | 3 +-- 2 files changed, 3 insertions(+), 6 deletions(-) diff --git a/src/FiveEval.h b/src/FiveEval.h index 51323fa..1906cbb 100644 --- a/src/FiveEval.h +++ b/src/FiveEval.h @@ -29,13 +29,11 @@ class FiveEval { // Get the rank of a hand comprising five cards, each represented by an // integer from 0 (resp. Ace of Spades) to 51 (resp. Two of Clubs) inclusive. // The higher the rank the better the hand. Two hands of equal rank tie. - short unsigned GetRank(int const, int const, int const, int const, - int const) const; + short unsigned GetRank(int, int, int, int, int) const; // Get the rank of a hand comprising seven cards, each represented by an // integer from 0 (resp. Ace of Spades) to 51 (resp. Two of Clubs) inclusive. // The higher the rank the better the hand. Two hands of equal rank tie. - short unsigned GetRank(int const, int const, int const, int const, - int const, const int, int const) const; + short unsigned GetRank(int, int, int, int, int, int, int) const; private: short unsigned *mRankPtr; short unsigned *mFlushRankPtr; diff --git a/src/SevenEval.h b/src/SevenEval.h index 46be9a8..3851cc6 100644 --- a/src/SevenEval.h +++ b/src/SevenEval.h @@ -29,8 +29,7 @@ class SevenEval { // Get the rank of a hand comprising seven cards, each represented by an // integer from 0 (resp. Ace of Spades) to 51 (resp. Two of Clubs) inclusive. // The higher the rank the better the hand. Two hands of equal rank tie. - short unsigned GetRank(int const, int const, int const, int const, int const, - int const, int const) const; + short unsigned GetRank(int, int, int, int, int, int, int) const; private: short unsigned *mRankPtr; short unsigned *mFlushRankPtr; From 57c8fb9179f1e35c21c11697dd72464511fb8c4b Mon Sep 17 00:00:00 2001 From: Ken Shackleton Date: Fri, 2 Sep 2016 23:11:58 +0100 Subject: [PATCH 02/28] Initial FiveEVal tests for high cards. --- CMakeLists.txt | 2 +- tests/five_eval_tests.cpp | 40 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 41 insertions(+), 1 deletion(-) create mode 100644 tests/five_eval_tests.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index dc5070e..a89b206 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -21,6 +21,6 @@ enable_testing() add_subdirectory(lib/gtest-1.7.0) include_directories(${gtest_SOURCE_DIR}/include ${gtest_SOURCE_DIR}) -add_executable(eval_tests tests/seven_eval_tests.cpp) +add_executable(eval_tests tests/seven_eval_tests.cpp tests/five_eval_tests.cpp) target_link_libraries(eval_tests gtest_main skpokereval) add_test(NAME GTests COMMAND eval_tests) diff --git a/tests/five_eval_tests.cpp b/tests/five_eval_tests.cpp new file mode 100644 index 0000000..cb355cb --- /dev/null +++ b/tests/five_eval_tests.cpp @@ -0,0 +1,40 @@ +#include +#include +#include "../src/FiveEval.h" + +TEST(FiveEval, HighCard) { + FiveEval const eval; + long rank = LONG_MIN; + for (int i = 5; i <= 12; ++i) { + int const I = ((12-i)<<2) + 1; // No flushes. + for (int j = 3; j < i; ++j) { + int const J = (12-j)<<2; + for (int k = 2; k < j; ++k) { + int const K = (12-k)<<2; + for (int l = 1; l < k; ++l) { + int const L = (12-l)<<2; + for (int m = 0; m < l && + !(i-m==4 || (i==12 && j==3)); ++m) { + int const M = (12-m)<<2; + int const next_rank = eval.GetRank(I, J, K, L, M); + ASSERT_GT(next_rank, rank) << "Rank " << next_rank << " at " + << I << ", " + << J << ", " + << K << ", " + << L << ", " + << M << " is invalid."; + rank = next_rank; + } + } + } + } + } +} + +TEST(FiveEval, WorstPairBeatsBestHighCard) { + FiveEval const eval; + int const rank_of_best_high_card = eval.GetRank(0, 4, 8, 12, 21); + int const rank_of_worst_pair = eval.GetRank(36, 40, 44, 48, 49); + ASSERT_LT(rank_of_best_high_card, rank_of_worst_pair); +} + From dfccffad0b8f3d849a92f4814aec68b26cd6caa6 Mon Sep 17 00:00:00 2001 From: Ken Shackleton Date: Fri, 2 Sep 2016 23:13:23 +0100 Subject: [PATCH 03/28] Increase ignorance. --- .gitignore | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index 68d70e6..dbea270 100644 --- a/.gitignore +++ b/.gitignore @@ -14,5 +14,6 @@ CTestTestfile.cmake eval_tests # Artifacts -libspecialkeval.a +libskpokereval.a +lib From 8b5c9ff4c98acd883c7e465e3791212aa39dc9c2 Mon Sep 17 00:00:00 2001 From: Ken Shackleton Date: Sat, 3 Sep 2016 06:38:46 +0100 Subject: [PATCH 04/28] Add trailing white space. --- src/FiveEval.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/FiveEval.cpp b/src/FiveEval.cpp index a896b06..1a89a17 100644 --- a/src/FiveEval.cpp +++ b/src/FiveEval.cpp @@ -187,3 +187,4 @@ short unsigned FiveEval::GetRank(int const card_one, int const card_two, } return best_rank_so_far; } + From e51347e44f1142608b254e45fbe2afabd54d917c Mon Sep 17 00:00:00 2001 From: Ken Shackleton Date: Sat, 3 Sep 2016 09:38:40 +0100 Subject: [PATCH 05/28] Complete FiveEval value tests. --- CMakeLists.txt | 2 +- tests/five_eval_tests.cpp | 265 ++++++++++++++++++++++++++++++++++++- tests/seven_eval_tests.cpp | 11 +- 3 files changed, 270 insertions(+), 8 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index a89b206..d3a6139 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -21,6 +21,6 @@ enable_testing() add_subdirectory(lib/gtest-1.7.0) include_directories(${gtest_SOURCE_DIR}/include ${gtest_SOURCE_DIR}) -add_executable(eval_tests tests/seven_eval_tests.cpp tests/five_eval_tests.cpp) +add_executable(eval_tests tests/five_eval_tests.cpp tests/seven_eval_tests.cpp) target_link_libraries(eval_tests gtest_main skpokereval) add_test(NAME GTests COMMAND eval_tests) diff --git a/tests/five_eval_tests.cpp b/tests/five_eval_tests.cpp index cb355cb..cc779dc 100644 --- a/tests/five_eval_tests.cpp +++ b/tests/five_eval_tests.cpp @@ -2,10 +2,18 @@ #include #include "../src/FiveEval.h" -TEST(FiveEval, HighCard) { +class FiveEvalTest : public ::testing::Test { +protected: + virtual void SetUp() {} + + virtual void TearDown() {} + FiveEval const eval; +}; + +TEST_F(FiveEvalTest, HighCard) { long rank = LONG_MIN; - for (int i = 5; i <= 12; ++i) { + for (int i = 5; i < 13; ++i) { int const I = ((12-i)<<2) + 1; // No flushes. for (int j = 3; j < i; ++j) { int const J = (12-j)<<2; @@ -13,8 +21,10 @@ TEST(FiveEval, HighCard) { int const K = (12-k)<<2; for (int l = 1; l < k; ++l) { int const L = (12-l)<<2; - for (int m = 0; m < l && - !(i-m==4 || (i==12 && j==3)); ++m) { + for (int m = 0; m < l; ++m) { + if (i-m == 4 || (i == 12 && j == 3)) { + continue; + } int const M = (12-m)<<2; int const next_rank = eval.GetRank(I, J, K, L, M); ASSERT_GT(next_rank, rank) << "Rank " << next_rank << " at " @@ -31,10 +41,253 @@ TEST(FiveEval, HighCard) { } } -TEST(FiveEval, WorstPairBeatsBestHighCard) { - FiveEval const eval; +TEST_F(FiveEvalTest, WorstPairBeatsBestHighCard) { + // Ace through to Jack inclusive, plus a Nine. No flush. int const rank_of_best_high_card = eval.GetRank(0, 4, 8, 12, 21); + // Pair of Twos with Five high. int const rank_of_worst_pair = eval.GetRank(36, 40, 44, 48, 49); ASSERT_LT(rank_of_best_high_card, rank_of_worst_pair); } +TEST_F(FiveEvalTest, Pair) { + long rank = LONG_MIN; + for (int i = 0; i < 13; ++i) { + int const I = (12-i)<<2; + for (int j = 2; j < 13; ++j) { + if (j == i) { + continue; + } + int const J = (12-j)<<2; + for (int k = 1; k < j; ++k) { + if (k == i) { + continue; + } + int const K = (12-k)<<2; + for (int l = 0; l < k; ++l) { + if (l == i) { + continue; + } + int const L = (12-l)<<2; + int const next_rank = eval.GetRank(I, I+1, J, K, L); + ASSERT_GT(next_rank, rank) << "Rank " << next_rank << " at " + << I << ", " + << I+1 << ", " + << J << ", " + << K << ", " + << L << " is invalid."; + rank = next_rank; + } + } + } + } +} + +TEST_F(FiveEvalTest, WorstTwoPairBeatsBestPair) { + // Pair of Aces with King, Queen and Jack. + int const rank_of_best_pair = eval.GetRank(0, 1, 4, 8, 12); + // Pair of Threes, Pair of Twos, Four high. + int const rank_of_worst_two_pair = eval.GetRank(44, 45, 48, 49, 40); + ASSERT_LT(rank_of_best_pair, rank_of_worst_two_pair); +} + +TEST_F(FiveEvalTest, TwoPair) { + long rank = LONG_MIN; + for (int i = 1; i < 13; ++i) { + int const I = (12-i)<<2; + for (int j = 0; j < i; ++j) { + int const J = (12-j)<<2; + for (int k = 0; k < 13; ++k) { + if (k == i || k == j) { + continue; + } + int const K = (12-k)<<2; + int const next_rank = eval.GetRank(I, I+1, J, J+1, K); + ASSERT_GT(next_rank, rank) << "Rank " << next_rank << " at " + << I << ", " + << I+1 << ", " + << J << ", " + << J+1 << ", " + << K << " is invalid."; + rank = next_rank; + } + } + } +} + +TEST_F(FiveEvalTest, WorstTripleBeatsBestTwoPair) { + // Pair of Aces, Pair of Kings, Queen high. + int const rank_of_best_two_pair = eval.GetRank(0, 1, 4, 5, 8); + // Triple Twos, Four high. + int const rank_of_worst_triple = eval.GetRank(48, 49, 50, 40, 44); + ASSERT_LT(rank_of_best_two_pair, rank_of_worst_triple); +} + +TEST_F(FiveEvalTest, Triple) { + long rank = LONG_MIN; + for (int i = 0; i < 13; ++i) { + int const I = (12-i)<<2; + for (int j = 1; j < 13; ++j) { + if (j == i) { + continue; + } + int const J = (12-j)<<2; + for (int k = 0; k < j; ++k) { + if (k == i) { + continue; + } + int const K = (12-k)<<2; + int const next_rank = eval.GetRank(I, I+1, I+2, J, K); + ASSERT_GT(next_rank, rank) << "Rank " << next_rank << " at " + << I << ", " + << I+1 << ", " + << I+2 << ", " + << J << ", " + << K << " is invalid."; + rank = next_rank; + } + } + } +} + +TEST_F(FiveEvalTest, WorstStraightBeatsBestTriple) { + // Triple Aces, King, Queen. + int const rank_of_best_triple = eval.GetRank(0, 1, 2, 4, 8); + // Straight Ace low. + int const rank_of_worst_straight = eval.GetRank(33, 36, 40, 44, 48); + ASSERT_LT(rank_of_best_triple, rank_of_worst_straight); +} + +TEST_F(FiveEvalTest, Straight) { + int rank = eval.GetRank(37, 40, 44, 48, 0); // Straight, Ace low. + for (int i = 0; i < 9; ++i) { + int const I = (12-i)<<2; + int const next_rank = eval.GetRank(I-15, I-12, I-8, I-4, I); + ASSERT_GT(next_rank, rank) << "Rank " << next_rank << " at " + << I-15 << ", " + << I-12 << ", " + << I-8 << ", " + << I-4 << ", " + << I << " is invalid."; + rank = next_rank; + } +} + +TEST_F(FiveEvalTest, WorstFlushBeatsBestStraight) { + // Straight Ace high. + int const rank_of_best_straight = eval.GetRank(0, 4, 8, 12, 17); + // Seven, Five, Four, Three, Two. + int const rank_of_worst_flush = eval.GetRank(28, 36, 40, 44, 48); + ASSERT_LT(rank_of_best_straight, rank_of_worst_flush); +} + +TEST_F(FiveEvalTest, Flush) { + long rank = LONG_MIN; + for (int i = 5; i < 13; ++i) { + int const I = (12-i)<<2; + for (int j = 3; j < i; ++j) { + int const J = (12-j)<<2; + for (int k = 2; k < j; ++k) { + int const K = (12-k)<<2; + for (int l = 1; l < k; ++l) { + int const L = (12-l)<<2; + for (int m = 0; m < l; ++m) { + if (i-m == 4 || (i == 12 && j == 3)) { + continue; + } + int const M = (12-m)<<2; + int const next_rank = eval.GetRank(I, J, K, L, M); + ASSERT_GT(next_rank, rank) << "Rank " << next_rank << " at " + << I << ", " + << J << ", " + << K << ", " + << L << ", " + << M << " is invalid."; + rank = next_rank; + } + } + } + } + } +} + +TEST_F(FiveEvalTest, WorstFullHouseBeatsBestFlush) { + // Ace, King, Queen, Jack, Nine + int const rank_of_best_flush = eval.GetRank(0, 4, 8, 12, 20); + // Triple Twos, Pair Threes. + int const rank_of_worst_full_house = eval.GetRank(48, 49, 50, 44, 45); + ASSERT_LT(rank_of_best_flush, rank_of_worst_full_house); +} + +TEST_F(FiveEvalTest, FullHouse) { + long rank = LONG_MIN; + for (int i = 0; i < 13; ++i) { + int const I = (12-i)<<2; + for (int j = 0; j < 13; ++j) { + if (j == i) { + continue; + } + int const J = (12-j)<<2; + int const next_rank = eval.GetRank(I, I+1, I+2, J, J+1); + ASSERT_GT(next_rank, rank) << "Rank " << next_rank << " at " + << I << ", " + << I+1 << ", " + << I+2 << ", " + << J << ", " + << J+1 << " is invalid."; + rank = next_rank; + } + } +} + +TEST_F(FiveEvalTest, WorstQuadBeatsBestFullHouse) { + // Triple Aces, Pair Kings. + int const rank_of_best_full_house = eval.GetRank(0, 1, 2, 4, 5); + // Quad Twos, Three high. + int const rank_of_worst_quad = eval.GetRank(48, 49, 50, 51, 44); + ASSERT_LT(rank_of_best_full_house, rank_of_worst_quad); +} + +TEST_F(FiveEvalTest, Quad) { + long rank = LONG_MIN; + for (int i = 0; i < 13; ++i) { + int const I = (12-i)<<2; + for (int j = 0; j < 13; ++j) { + if (j == i) { + continue; + } + int const J = (12-j)<<2; + int const next_rank = eval.GetRank(I, I+1, I+2, I+3, J); + ASSERT_GT(next_rank, rank) << "Rank " << next_rank << " at " + << I << ", " + << I+1 << ", " + << I+2 << ", " + << I+3 << ", " + << J << " is invalid."; + rank = next_rank; + } + } +} + +TEST_F(FiveEvalTest, WorstStraightFlushBeatsBestQuad) { + // Quad Aces, King high. + int const rank_of_best_quad = eval.GetRank(0, 1, 2, 3, 4); + // Straight flush Ace low. + int const rank_of_worst_straight_flush = eval.GetRank(36, 40, 44, 48, 0); + ASSERT_LT(rank_of_best_quad, rank_of_worst_straight_flush); +} + +TEST_F(FiveEvalTest, StraightFlush) { + int rank = eval.GetRank(36, 40, 44, 48, 0); // Straight flush, Ace low. + for (int i = 0; i < 9; ++i) { + int const I = (12-i)<<2; + int const next_rank = eval.GetRank(I-16, I-12, I-8, I-4, I); + ASSERT_GT(next_rank, rank) << "Rank " << next_rank << " at " + << I-16 << ", " + << I-12 << ", " + << I-8 << ", " + << I-4 << ", " + << I << " is invalid."; + rank = next_rank; + } +} + diff --git a/tests/seven_eval_tests.cpp b/tests/seven_eval_tests.cpp index 0368f4f..a0faf83 100644 --- a/tests/seven_eval_tests.cpp +++ b/tests/seven_eval_tests.cpp @@ -2,9 +2,17 @@ #include "../src/FiveEval.h" #include "../src/SevenEval.h" -TEST(SevenEval, Regression) { +class SevenEvalTest : public ::testing::Test { +protected: + virtual void SetUp() {} + + virtual void TearDown() {} + FiveEval const five_eval; SevenEval const seven_eval; +}; + +TEST_F(SevenEvalTest, Regression) { for (int i=0; i<46; ++i) { for (int j=i+1; j<47; ++j) { for (int k=j+1; k<48; ++k) { @@ -31,3 +39,4 @@ TEST(SevenEval, Regression) { } } } + From 3c444dfca4a43eb2aa37e7cd3131663568bfc079 Mon Sep 17 00:00:00 2001 From: Ken Shackleton Date: Sun, 4 Sep 2016 08:17:39 +0100 Subject: [PATCH 06/28] Inline flush check key. --- src/SKConfig.h | 2 ++ src/SevenEval.cpp | 3 +-- 2 files changed, 3 insertions(+), 2 deletions(-) create mode 100644 src/SKConfig.h diff --git a/src/SKConfig.h b/src/SKConfig.h new file mode 100644 index 0000000..413561f --- /dev/null +++ b/src/SKConfig.h @@ -0,0 +1,2 @@ +#define SK_POKER_EVAL_VERSION_MAJOR 1 +#define SK_POKER_EVAL_VERSION_MINOR 3 diff --git a/src/SevenEval.cpp b/src/SevenEval.cpp index 45093d2..f51d5fd 100644 --- a/src/SevenEval.cpp +++ b/src/SevenEval.cpp @@ -197,8 +197,7 @@ short unsigned SevenEval::GetRank(int const i, int const j, int const k, long unsigned key = mDeckcardsKey[i] + mDeckcardsKey[j] + mDeckcardsKey[k] + mDeckcardsKey[l] + mDeckcardsKey[m] + mDeckcardsKey[n] + mDeckcardsKey[p]; // Tear off the flush check strip. - int const flush_check_key = (const int) (key & SUIT_BIT_MASK); - short flush_suit = mFlushCheck[flush_check_key]; + short flush_suit = mFlushCheck[key & SUIT_BIT_MASK]; if (flush_suit == NOT_A_FLUSH) { // Tear off the non-flush key strip, and look up the rank. key = (key >> NON_FLUSH_BIT_SHIFT); From 13d4133ff196be36ccba03917f6983ff4052a1cf Mon Sep 17 00:00:00 2001 From: Ken Shackleton Date: Sun, 4 Sep 2016 08:37:32 +0100 Subject: [PATCH 07/28] Key can be int. --- src/SevenEval.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/SevenEval.cpp b/src/SevenEval.cpp index f51d5fd..9d4b39d 100644 --- a/src/SevenEval.cpp +++ b/src/SevenEval.cpp @@ -194,10 +194,10 @@ short unsigned SevenEval::GetRank(int const i, int const j, int const k, int const l, int const m, int const n, int const p) const { // Create a 7-card hand key by adding up each of the card keys. - long unsigned key = mDeckcardsKey[i] + mDeckcardsKey[j] + mDeckcardsKey[k] + + int unsigned key = mDeckcardsKey[i] + mDeckcardsKey[j] + mDeckcardsKey[k] + mDeckcardsKey[l] + mDeckcardsKey[m] + mDeckcardsKey[n] + mDeckcardsKey[p]; // Tear off the flush check strip. - short flush_suit = mFlushCheck[key & SUIT_BIT_MASK]; + short const flush_suit = mFlushCheck[key & SUIT_BIT_MASK]; if (flush_suit == NOT_A_FLUSH) { // Tear off the non-flush key strip, and look up the rank. key = (key >> NON_FLUSH_BIT_SHIFT); From 43045d810efb2c30dec0497aec6fa0a9fd8df874 Mon Sep 17 00:00:00 2001 From: Ken Shackleton Date: Sun, 4 Sep 2016 09:18:34 +0100 Subject: [PATCH 08/28] Tidy eval name, alignment. --- src/SevenEval.cpp | 31 +++++++++++++++---------------- 1 file changed, 15 insertions(+), 16 deletions(-) diff --git a/src/SevenEval.cpp b/src/SevenEval.cpp index 9d4b39d..f16285d 100644 --- a/src/SevenEval.cpp +++ b/src/SevenEval.cpp @@ -8,20 +8,20 @@ SevenEval::SevenEval() : mRankPtr(new short unsigned[CIRCUMFERENCE_SEVEN]), int const face_flush[13] = {ACE_FLUSH, KING_FLUSH, QUEEN_FLUSH, JACK_FLUSH, TEN_FLUSH, NINE_FLUSH, EIGHT_FLUSH, SEVEN_FLUSH, SIX_FLUSH, FIVE_FLUSH, FOUR_FLUSH, THREE_FLUSH, TWO_FLUSH}; - for (int n = 0; n < 13; n++) { + for (int n = 0; n < 13; ++n) { int const N = n<<2; - long unsigned const start = face[n] << NON_FLUSH_BIT_SHIFT; - mDeckcardsKey[N] = start + SPADE; + int unsigned const start = face[n] << NON_FLUSH_BIT_SHIFT; + mDeckcardsKey[N ] = start + SPADE; mDeckcardsKey[N+1] = start + HEART; mDeckcardsKey[N+2] = start + DIAMOND; mDeckcardsKey[N+3] = start + CLUB; - mDeckcardsFlush[N] = (short unsigned) face_flush[n]; - mDeckcardsFlush[N+1] = (short unsigned) face_flush[n]; - mDeckcardsFlush[N+2] = (short unsigned) face_flush[n]; - mDeckcardsFlush[N+3] = (short unsigned) face_flush[n]; + mDeckcardsFlush[N ] = face_flush[n]; + mDeckcardsFlush[N+1] = face_flush[n]; + mDeckcardsFlush[N+2] = face_flush[n]; + mDeckcardsFlush[N+3] = face_flush[n]; - mDeckcardsSuit[N] = SPADE; + mDeckcardsSuit[N ] = SPADE; mDeckcardsSuit[N+1] = HEART; mDeckcardsSuit[N+2] = DIAMOND; mDeckcardsSuit[N+3] = CLUB; @@ -30,7 +30,7 @@ SevenEval::SevenEval() : mRankPtr(new short unsigned[CIRCUMFERENCE_SEVEN]), int count = 0; // Generate seven-ranks from five-ranks. - FiveEval five_card_evaluator; + FiveEval const eval; // Non-flush ranks. for (int i = 1; i < 13; ++i) { @@ -45,8 +45,8 @@ SevenEval::SevenEval() : mRankPtr(new short unsigned[CIRCUMFERENCE_SEVEN]), face[m] + face[n] + face[p]; // The (4*i)+0 and (4*m)+1 trick prevents flushes. short unsigned const rank = - five_card_evaluator.GetRank(i<<2, j<<2, k<<2, l<<2, - (m<<2)+1, (n<<2)+1, (p<<2)+1); + eval.GetRank(i<<2, j<<2, k<<2, l<<2, (m<<2)+1, (n<<2)+1, + (p<<2)+1); mRankPtr[key < CIRCUMFERENCE_SEVEN ? key : key - CIRCUMFERENCE_SEVEN] = rank; ++count; @@ -76,8 +76,7 @@ SevenEval::SevenEval() : mRankPtr(new short unsigned[CIRCUMFERENCE_SEVEN]), int const key = face_flush[i] + face_flush[j] + face_flush[k] + face_flush[l] + face_flush[m] + face_flush[n] + face_flush[p]; - mFlushRankPtr[key] = - five_card_evaluator.GetRank(I, J, K, L, M, N, p<<2); + mFlushRankPtr[key] = eval.GetRank(I, J, K, L, M, N, p<<2); ++count; } } @@ -103,8 +102,7 @@ SevenEval::SevenEval() : mRankPtr(new short unsigned[CIRCUMFERENCE_SEVEN]), face_flush[l] + face_flush[m] + face_flush[n]; // The Two of Clubs is the card at index 51; the other six cards // all have the spade suit. - mFlushRankPtr[key] = - five_card_evaluator.GetRank(I, J, K, L, M, n<<2, 51); + mFlushRankPtr[key] = eval.GetRank(I, J, K, L, M, n<<2, 51); ++count; } } @@ -125,7 +123,7 @@ SevenEval::SevenEval() : mRankPtr(new short unsigned[CIRCUMFERENCE_SEVEN]), for (int m = 0; m < l; ++m) { int const key = face_flush[i] + face_flush[j] + face_flush[k] + face_flush[l] + face_flush[m]; - mFlushRankPtr[key] = five_card_evaluator.GetRank(I, J, K, L, m<<2); + mFlushRankPtr[key] = eval.GetRank(I, J, K, L, m<<2); ++count; } } @@ -216,3 +214,4 @@ short unsigned SevenEval::GetRank(int const i, int const j, int const k, (mDeckcardsSuit[p] == flush_suit ? mDeckcardsFlush[p] : 0); return mFlushRankPtr[flush_key]; } + From 67e2ed18981f605b31709c7365de412613df923b Mon Sep 17 00:00:00 2001 From: Ken Shackleton Date: Sun, 4 Sep 2016 09:22:07 +0100 Subject: [PATCH 09/28] Card keys must be 32-bit. --- CMakeLists.txt | 2 +- src/SevenEval.cpp | 4 ++-- src/SevenEval.h | 13 +++++++------ 3 files changed, 10 insertions(+), 9 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index d3a6139..9e2731f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -11,7 +11,7 @@ configure_file ( "${PROJECT_BINARY_DIR}/src/SKConfig.h" ) -set(CMAKE_CXX_FLAGS "-g -Wall") +set(CMAKE_CXX_FLAGS "-g -Wall --std=c++11") # Build add_library(skpokereval src/FiveEval.cpp src/SevenEval.cpp) diff --git a/src/SevenEval.cpp b/src/SevenEval.cpp index f16285d..94eead4 100644 --- a/src/SevenEval.cpp +++ b/src/SevenEval.cpp @@ -192,10 +192,10 @@ short unsigned SevenEval::GetRank(int const i, int const j, int const k, int const l, int const m, int const n, int const p) const { // Create a 7-card hand key by adding up each of the card keys. - int unsigned key = mDeckcardsKey[i] + mDeckcardsKey[j] + mDeckcardsKey[k] + + uint_fast32_t key = mDeckcardsKey[i] + mDeckcardsKey[j] + mDeckcardsKey[k] + mDeckcardsKey[l] + mDeckcardsKey[m] + mDeckcardsKey[n] + mDeckcardsKey[p]; // Tear off the flush check strip. - short const flush_suit = mFlushCheck[key & SUIT_BIT_MASK]; + int_fast16_t const flush_suit = mFlushCheck[key & SUIT_BIT_MASK]; if (flush_suit == NOT_A_FLUSH) { // Tear off the non-flush key strip, and look up the rank. key = (key >> NON_FLUSH_BIT_SHIFT); diff --git a/src/SevenEval.h b/src/SevenEval.h index 3851cc6..a1e04a4 100644 --- a/src/SevenEval.h +++ b/src/SevenEval.h @@ -20,6 +20,7 @@ #ifndef SKPOKEREVAL_SEVENEVAL_H #define SKPOKEREVAL_SEVENEVAL_H +#include #include "Constants.h" class SevenEval { @@ -31,12 +32,12 @@ class SevenEval { // The higher the rank the better the hand. Two hands of equal rank tie. short unsigned GetRank(int, int, int, int, int, int, int) const; private: - short unsigned *mRankPtr; - short unsigned *mFlushRankPtr; - long unsigned mDeckcardsKey[DECK_SIZE]; - short unsigned mDeckcardsFlush[DECK_SIZE]; - short unsigned mDeckcardsSuit[DECK_SIZE]; - short mFlushCheck[MAX_FLUSH_CHECK_SUM+1]; + uint16_t *mRankPtr; + uint16_t *mFlushRankPtr; + uint32_t mDeckcardsKey[DECK_SIZE]; + uint16_t mDeckcardsFlush[DECK_SIZE]; + uint16_t mDeckcardsSuit[DECK_SIZE]; + int16_t mFlushCheck[MAX_FLUSH_CHECK_SUM+1]; }; #endif // SKPOKEREVAL_SEVENEVAL_H From 44f7d97641b4356f48bf5a0b41ff1c2d6a4e98e7 Mon Sep 17 00:00:00 2001 From: Ken Shackleton Date: Sun, 4 Sep 2016 09:27:22 +0100 Subject: [PATCH 10/28] Tidy indentation. --- src/SevenEval.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/SevenEval.cpp b/src/SevenEval.cpp index 94eead4..7036521 100644 --- a/src/SevenEval.cpp +++ b/src/SevenEval.cpp @@ -189,8 +189,7 @@ SevenEval::~SevenEval() { } short unsigned SevenEval::GetRank(int const i, int const j, int const k, - int const l, int const m, int const n, - int const p) const { + int const l, int const m, int const n, int const p) const { // Create a 7-card hand key by adding up each of the card keys. uint_fast32_t key = mDeckcardsKey[i] + mDeckcardsKey[j] + mDeckcardsKey[k] + mDeckcardsKey[l] + mDeckcardsKey[m] + mDeckcardsKey[n] + mDeckcardsKey[p]; From bf0ef0f1c3f9353f77ab8d50b82fb4bb39119798 Mon Sep 17 00:00:00 2001 From: Ken Shackleton Date: Sun, 4 Sep 2016 10:20:49 +0100 Subject: [PATCH 11/28] Remove stray file. --- src/SKConfig.h | 2 -- 1 file changed, 2 deletions(-) delete mode 100644 src/SKConfig.h diff --git a/src/SKConfig.h b/src/SKConfig.h deleted file mode 100644 index 413561f..0000000 --- a/src/SKConfig.h +++ /dev/null @@ -1,2 +0,0 @@ -#define SK_POKER_EVAL_VERSION_MAJOR 1 -#define SK_POKER_EVAL_VERSION_MINOR 3 From 52c5e7ce7080a5eb79734df08f6609193f56396b Mon Sep 17 00:00:00 2001 From: Ken Shackleton Date: Sun, 4 Sep 2016 14:40:55 +0100 Subject: [PATCH 12/28] Convenience build command. --- build.sh | 2 ++ 1 file changed, 2 insertions(+) create mode 100755 build.sh diff --git a/build.sh b/build.sh new file mode 100755 index 0000000..b514799 --- /dev/null +++ b/build.sh @@ -0,0 +1,2 @@ +./configure && cmake . && make && ctest + From 1acfc1d1fe746182a3926ceed67a0c9b84b22d3c Mon Sep 17 00:00:00 2001 From: Ken Shackleton Date: Sun, 4 Sep 2016 14:42:49 +0100 Subject: [PATCH 13/28] Change C++11 setting. Add patch version. Add commit information. --- .gitignore | 1 + CMakeLists.txt | 20 ++++++++++++++++---- src/SKConfig.h.in | 4 ++++ 3 files changed, 21 insertions(+), 4 deletions(-) diff --git a/.gitignore b/.gitignore index dbea270..4308c6a 100644 --- a/.gitignore +++ b/.gitignore @@ -16,4 +16,5 @@ eval_tests # Artifacts libskpokereval.a lib +SKConfig.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 9e2731f..97c03bf 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,17 +1,28 @@ -cmake_minimum_required (VERSION 2.8.7) +cmake_minimum_required (VERSION 3.1.0 FATAL_ERROR) set(PROJECT_NAME SKPokerEval) project(${PROJECT_NAME}) # Versioning. -set (SK_POKER_EVAL_VERSION_MAJOR 1) -set (SK_POKER_EVAL_VERSION_MINOR 3) +set(SK_POKER_EVAL_VERSION_MAJOR 1) +set(SK_POKER_EVAL_VERSION_MINOR 3) +set(SK_POKER_EVAL_VERSION_PATCH 0) + +# Get the current commit. +execute_process( + COMMAND git log -1 --format=%H + WORKING_DIRECTORY ${CMAKE_SOURCE_DIR} + OUTPUT_VARIABLE SK_POKER_EVAL_GIT_COMMIT + OUTPUT_STRIP_TRAILING_WHITESPACE +) + configure_file ( "${PROJECT_SOURCE_DIR}/src/SKConfig.h.in" "${PROJECT_BINARY_DIR}/src/SKConfig.h" ) -set(CMAKE_CXX_FLAGS "-g -Wall --std=c++11") +set(CMAKE_CXX_FLAGS "-g -Wall") +set(CMAKE_CXX_STANDARD 11) # Build add_library(skpokereval src/FiveEval.cpp src/SevenEval.cpp) @@ -24,3 +35,4 @@ include_directories(${gtest_SOURCE_DIR}/include ${gtest_SOURCE_DIR}) add_executable(eval_tests tests/five_eval_tests.cpp tests/seven_eval_tests.cpp) target_link_libraries(eval_tests gtest_main skpokereval) add_test(NAME GTests COMMAND eval_tests) + diff --git a/src/SKConfig.h.in b/src/SKConfig.h.in index 9928000..3d2742e 100644 --- a/src/SKConfig.h.in +++ b/src/SKConfig.h.in @@ -1,2 +1,6 @@ #define SK_POKER_EVAL_VERSION_MAJOR @SK_POKER_EVAL_VERSION_MAJOR@ #define SK_POKER_EVAL_VERSION_MINOR @SK_POKER_EVAL_VERSION_MINOR@ +#define SK_POKER_EVAL_VERSION_PATCH @SK_POKER_EVAL_VERSION_PATCH@ + +#define SK_POKER_EVAL_GIT_COMMIT @SK_POKER_EVAL_GIT_COMMIT@ + From 8e7386f76211592f15cb4bb145c54b462c24e120 Mon Sep 17 00:00:00 2001 From: Ken Shackleton Date: Sun, 4 Sep 2016 15:05:53 +0100 Subject: [PATCH 14/28] Add shebang. --- build.sh | 1 + 1 file changed, 1 insertion(+) diff --git a/build.sh b/build.sh index b514799..67ae953 100755 --- a/build.sh +++ b/build.sh @@ -1,2 +1,3 @@ +#!/bin/sh ./configure && cmake . && make && ctest From 773344313eaa401a1c403f4b6b441643ad1d9a05 Mon Sep 17 00:00:00 2001 From: Ken Shackleton Date: Sun, 4 Sep 2016 15:06:24 +0100 Subject: [PATCH 15/28] Organise building a bit. --- .gitignore | 1 + CMakeLists.txt | 12 ++++++++++-- src/CMakeLists.txt | 5 +++++ 3 files changed, 16 insertions(+), 2 deletions(-) diff --git a/.gitignore b/.gitignore index 4308c6a..c2f6c4f 100644 --- a/.gitignore +++ b/.gitignore @@ -14,6 +14,7 @@ CTestTestfile.cmake eval_tests # Artifacts +build/ libskpokereval.a lib SKConfig.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 97c03bf..83431f7 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -18,14 +18,22 @@ execute_process( configure_file ( "${PROJECT_SOURCE_DIR}/src/SKConfig.h.in" - "${PROJECT_BINARY_DIR}/src/SKConfig.h" + "${PROJECT_BINARY_DIR}/generated/SKConfig.h" ) +# Includes. +include_directories("${PROJECT_SOURCE_DIR}/generated") + +# Output directories. +set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/build) +set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/build) +set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/build) + set(CMAKE_CXX_FLAGS "-g -Wall") set(CMAKE_CXX_STANDARD 11) # Build -add_library(skpokereval src/FiveEval.cpp src/SevenEval.cpp) +add_subdirectory(src) # Testing enable_testing() diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index e69de29..920552a 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -0,0 +1,5 @@ +add_library(skpokereval + FiveEval.cpp + SevenEval.cpp +) + From 672054b2d563c5279d12926ddf57645896916031 Mon Sep 17 00:00:00 2001 From: Ken Shackleton Date: Sun, 4 Sep 2016 17:31:30 +0100 Subject: [PATCH 16/28] Travis configuration. --- .travis.yml | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index 2acbbae..99f82f2 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,6 +1,19 @@ -language: cpp +os: + - linux + +sudo: required +dist: trusty + compiler: - gcc - clang -script: ./configure && cmake . && make && ctest + +language: cpp + +install: + - if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then + sudo apt-get install cmake; + fi + +script: ./build From 36625e57e2885ec216b9618fc46a5ef1f2404aa1 Mon Sep 17 00:00:00 2001 From: Ken Shackleton Date: Sun, 4 Sep 2016 17:36:59 +0100 Subject: [PATCH 17/28] Complete build instruction in Travis config. --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 99f82f2..f735857 100644 --- a/.travis.yml +++ b/.travis.yml @@ -15,5 +15,5 @@ install: sudo apt-get install cmake; fi -script: ./build +script: ./build.sh From 4bea7a1eceb1859c7a8b935e0c4e6d6cb736d4c4 Mon Sep 17 00:00:00 2001 From: Ken Shackleton Date: Sun, 4 Sep 2016 17:41:47 +0100 Subject: [PATCH 18/28] Log version of CMake. --- .travis.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.travis.yml b/.travis.yml index f735857..431c671 100644 --- a/.travis.yml +++ b/.travis.yml @@ -13,6 +13,7 @@ language: cpp install: - if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then sudo apt-get install cmake; + cmake --version; fi script: ./build.sh From 69aa459994f8b47b02fa98a32e394b6dca0099ff Mon Sep 17 00:00:00 2001 From: Ken Shackleton Date: Sun, 4 Sep 2016 17:57:30 +0100 Subject: [PATCH 19/28] count variable is never read. --- src/SevenEval.cpp | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/src/SevenEval.cpp b/src/SevenEval.cpp index 7036521..4cff663 100644 --- a/src/SevenEval.cpp +++ b/src/SevenEval.cpp @@ -27,8 +27,6 @@ SevenEval::SevenEval() : mRankPtr(new short unsigned[CIRCUMFERENCE_SEVEN]), mDeckcardsSuit[N+3] = CLUB; } - int count = 0; - // Generate seven-ranks from five-ranks. FiveEval const eval; @@ -49,7 +47,6 @@ SevenEval::SevenEval() : mRankPtr(new short unsigned[CIRCUMFERENCE_SEVEN]), (p<<2)+1); mRankPtr[key < CIRCUMFERENCE_SEVEN ? key : key - CIRCUMFERENCE_SEVEN] = rank; - ++count; } } } @@ -77,7 +74,6 @@ SevenEval::SevenEval() : mRankPtr(new short unsigned[CIRCUMFERENCE_SEVEN]), face_flush[l] + face_flush[m] + face_flush[n] + face_flush[p]; mFlushRankPtr[key] = eval.GetRank(I, J, K, L, M, N, p<<2); - ++count; } } } @@ -101,9 +97,8 @@ SevenEval::SevenEval() : mRankPtr(new short unsigned[CIRCUMFERENCE_SEVEN]), int const key = face_flush[i] + face_flush[j] + face_flush[k] + face_flush[l] + face_flush[m] + face_flush[n]; // The Two of Clubs is the card at index 51; the other six cards - // all have the spade suit. + // all have the Spade suit. mFlushRankPtr[key] = eval.GetRank(I, J, K, L, M, n<<2, 51); - ++count; } } } @@ -124,7 +119,6 @@ SevenEval::SevenEval() : mRankPtr(new short unsigned[CIRCUMFERENCE_SEVEN]), int const key = face_flush[i] + face_flush[j] + face_flush[k] + face_flush[l] + face_flush[m]; mFlushRankPtr[key] = eval.GetRank(I, J, K, L, m<<2); - ++count; } } } From 2b20c1a8e740208c3362f17618d57f5d3561af14 Mon Sep 17 00:00:00 2001 From: Ken Shackleton Date: Sun, 4 Sep 2016 18:08:15 +0100 Subject: [PATCH 20/28] Exit initialisation loop sooner. --- src/SevenEval.cpp | 30 +++++++++++++++++++++--------- 1 file changed, 21 insertions(+), 9 deletions(-) diff --git a/src/SevenEval.cpp b/src/SevenEval.cpp index 4cff663..58c6f5b 100644 --- a/src/SevenEval.cpp +++ b/src/SevenEval.cpp @@ -32,22 +32,34 @@ SevenEval::SevenEval() : mRankPtr(new short unsigned[CIRCUMFERENCE_SEVEN]), // Non-flush ranks. for (int i = 1; i < 13; ++i) { + int const I = i<<2; for (int j = 1; j <= i; ++j) { + int const J = j<<2; for (int k = 1; k <= j; ++k) { + int const K = k<<2; for (int l = 0; l <= k; ++l) { + int const L = l<<2; for (int m = 0; m <= l; ++m) { + if (i == m) { + break; + } + int const M = (m<<2)+1; for (int n = 0; n <= m; ++n) { + if (j == n) { + break; + } + int const N = (n<<2)+1; for (int p = 0; p <= n; ++p) { - if (i != m && j != n && k != p) { - int const key = face[i] + face[j] + face[k] + face[l] + - face[m] + face[n] + face[p]; - // The (4*i)+0 and (4*m)+1 trick prevents flushes. - short unsigned const rank = - eval.GetRank(i<<2, j<<2, k<<2, l<<2, (m<<2)+1, (n<<2)+1, - (p<<2)+1); - mRankPtr[key < CIRCUMFERENCE_SEVEN ? - key : key - CIRCUMFERENCE_SEVEN] = rank; + if (k == p) { + break; } + int const P = (p<<2)+1; + int const key = face[i] + face[j] + face[k] + face[l] + + face[m] + face[n] + face[p]; + // The (4*i)+0 and (4*m)+1 trick prevents flushes. + short unsigned const rank = eval.GetRank(I, J, K, L, M, N, P); + mRankPtr[key < CIRCUMFERENCE_SEVEN ? + key : key - CIRCUMFERENCE_SEVEN] = rank; } } } From 2972375b1467b4af68fbc1cf568cfb70f904dbad Mon Sep 17 00:00:00 2001 From: Ken Shackleton Date: Sun, 4 Sep 2016 18:12:01 +0100 Subject: [PATCH 21/28] More succinct. --- src/SevenEval.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/SevenEval.cpp b/src/SevenEval.cpp index 58c6f5b..7db4b56 100644 --- a/src/SevenEval.cpp +++ b/src/SevenEval.cpp @@ -203,7 +203,7 @@ short unsigned SevenEval::GetRank(int const i, int const j, int const k, int_fast16_t const flush_suit = mFlushCheck[key & SUIT_BIT_MASK]; if (flush_suit == NOT_A_FLUSH) { // Tear off the non-flush key strip, and look up the rank. - key = (key >> NON_FLUSH_BIT_SHIFT); + key >>= NON_FLUSH_BIT_SHIFT; // Take key modulo the circumference. return mRankPtr[(key < CIRCUMFERENCE_SEVEN ? key : key - CIRCUMFERENCE_SEVEN)]; From 7f86026ebdbeefeeda462ecf25a5b0b7cce15b1c Mon Sep 17 00:00:00 2001 From: Ken Shackleton Date: Sun, 4 Sep 2016 18:18:22 +0100 Subject: [PATCH 22/28] More succinct. --- src/SevenEval.cpp | 29 ++++++++++------------------- 1 file changed, 10 insertions(+), 19 deletions(-) diff --git a/src/SevenEval.cpp b/src/SevenEval.cpp index 7db4b56..9a03c1d 100644 --- a/src/SevenEval.cpp +++ b/src/SevenEval.cpp @@ -39,27 +39,18 @@ SevenEval::SevenEval() : mRankPtr(new short unsigned[CIRCUMFERENCE_SEVEN]), int const K = k<<2; for (int l = 0; l <= k; ++l) { int const L = l<<2; - for (int m = 0; m <= l; ++m) { - if (i == m) { - break; - } + for (int m = 0; m <= l && m < i; ++m) { int const M = (m<<2)+1; - for (int n = 0; n <= m; ++n) { - if (j == n) { - break; - } + for (int n = 0; n <= m && n < j; ++n) { int const N = (n<<2)+1; - for (int p = 0; p <= n; ++p) { - if (k == p) { - break; - } + for (int p = 0; p <= n && p < k; ++p) { int const P = (p<<2)+1; int const key = face[i] + face[j] + face[k] + face[l] + - face[m] + face[n] + face[p]; + face[m] + face[n] + face[p]; // The (4*i)+0 and (4*m)+1 trick prevents flushes. short unsigned const rank = eval.GetRank(I, J, K, L, M, N, P); mRankPtr[key < CIRCUMFERENCE_SEVEN ? - key : key - CIRCUMFERENCE_SEVEN] = rank; + key : key - CIRCUMFERENCE_SEVEN] = rank; } } } @@ -73,15 +64,15 @@ SevenEval::SevenEval() : mRankPtr(new short unsigned[CIRCUMFERENCE_SEVEN]), int const I = i<<2; for (int j = 5; j < i; ++j) { int const J = j<<2; - for(int k = 4; k < j; ++k) { + for (int k = 4; k < j; ++k) { int const K = k<<2; - for(int l = 3; l < k; ++l) { + for (int l = 3; l < k; ++l) { int const L = l<<2; - for(int m = 2; m < l; ++m) { + for (int m = 2; m < l; ++m) { int const M = m<<2; - for(int n = 1; n < m; ++n) { + for (int n = 1; n < m; ++n) { int const N = n<<2; - for(int p = 0; p < n; ++p) { + for (int p = 0; p < n; ++p) { int const key = face_flush[i] + face_flush[j] + face_flush[k] + face_flush[l] + face_flush[m] + face_flush[n] + face_flush[p]; From 2059d17b770a07720e545acabc4eb678b6900ebe Mon Sep 17 00:00:00 2001 From: Ken Shackleton Date: Sun, 4 Sep 2016 20:28:20 +0100 Subject: [PATCH 23/28] Test FiveEval.GetRank for seven. --- tests/five_eval_tests.cpp | 52 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 52 insertions(+) diff --git a/tests/five_eval_tests.cpp b/tests/five_eval_tests.cpp index cc779dc..dba6924 100644 --- a/tests/five_eval_tests.cpp +++ b/tests/five_eval_tests.cpp @@ -291,3 +291,55 @@ TEST_F(FiveEvalTest, StraightFlush) { } } +TEST_F(FiveEvalTest, SevenByFive) { + int five[5]; + int seven[7]; + for (int i = 6; i < 51; ++i) { + seven[0] = i; + for (int j = 5; j < i; ++j) { + seven[1] = j; + for (int k = 4; k < j; ++k) { + seven[2] = k; + for (int l = 3; l < k; ++l) { + seven[3] = l; + for (int m = 2; m < l; ++m) { + seven[4] = m; + for (int n = 1; n < m; ++n) { + seven[5] = n; + for (int p = 0; p < n; ++p) { + seven[6] = p; + short unsigned rbf = 0; + int v = 0; + for (int x = 1; x < 7; ++x) { + for (int y = 0; y < x; ++y) { + v = 0; + for (int z = 0; z < 7; ++z) { + if (z != x && z != y) { + five[v++] = seven[z]; + } + } + short unsigned const rank = eval.GetRank(five[0], five[1], + five[2], five[3], five[4]); + if (rbf < rank) { + rbf = rank; + } + } + } + short const rbs = eval.GetRank(i, j, k, l, m, n, p); + ASSERT_EQ(rbf, rbs) << "Rank " << rbs << " at " + << i << ", " + << j << ", " + << k << ", " + << l << ", " + << m << ", " + << n << ", " + << p << " is invalid."; + } + } + } + } + } + } + } +} + From 2f8664caa61e9b9e81832b07f984158ad26dea34 Mon Sep 17 00:00:00 2001 From: Ken Shackleton Date: Sun, 4 Sep 2016 20:39:48 +0100 Subject: [PATCH 24/28] Verbose, to show GTest results in log. --- build.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.sh b/build.sh index 67ae953..da2ac46 100755 --- a/build.sh +++ b/build.sh @@ -1,3 +1,3 @@ #!/bin/sh -./configure && cmake . && make && ctest +./configure && cmake . && make && ctest --verbose From c202935a46790c5a27627e36cc0a8fcdd850657d Mon Sep 17 00:00:00 2001 From: Ken Shackleton Date: Sun, 4 Sep 2016 20:46:32 +0100 Subject: [PATCH 25/28] Rename two tests. --- tests/five_eval_tests.cpp | 2 +- tests/seven_eval_tests.cpp | 16 ++++++++-------- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/tests/five_eval_tests.cpp b/tests/five_eval_tests.cpp index dba6924..cebf7e8 100644 --- a/tests/five_eval_tests.cpp +++ b/tests/five_eval_tests.cpp @@ -291,7 +291,7 @@ TEST_F(FiveEvalTest, StraightFlush) { } } -TEST_F(FiveEvalTest, SevenByFive) { +TEST_F(FiveEvalTest, SevenCardHand) { int five[5]; int seven[7]; for (int i = 6; i < 51; ++i) { diff --git a/tests/seven_eval_tests.cpp b/tests/seven_eval_tests.cpp index a0faf83..8684dc9 100644 --- a/tests/seven_eval_tests.cpp +++ b/tests/seven_eval_tests.cpp @@ -12,14 +12,14 @@ class SevenEvalTest : public ::testing::Test { SevenEval const seven_eval; }; -TEST_F(SevenEvalTest, Regression) { - for (int i=0; i<46; ++i) { - for (int j=i+1; j<47; ++j) { - for (int k=j+1; k<48; ++k) { - for (int l=k+1; l<49; ++l) { - for (int m=l+1; m<50; ++m) { - for (int n=m+1; n<51; ++n) { - for (int p=n+1; p<52; ++p) { +TEST_F(SevenEvalTest, CompareWithFiveEval) { + for (int i = 0; i < 46; ++i) { + for (int j = i+1; j < 47; ++j) { + for (int k = j+1; k < 48; ++k) { + for (int l = k+1; l < 49; ++l) { + for (int m = l+1; m < 50; ++m) { + for (int n = m+1; n < 51; ++n) { + for (int p = n+1; p < 52; ++p) { int const five_rank = five_eval.GetRank(i, j, k, l, m, n, p); int const seven_rank = seven_eval.GetRank(i, j, k, l, m, n, p); ASSERT_EQ(five_rank, seven_rank) << "Ranks at " From fa384f28194f68c47dd4e27b83d0ac0373857269 Mon Sep 17 00:00:00 2001 From: Ken Shackleton Date: Fri, 9 Sep 2016 20:58:52 +0100 Subject: [PATCH 26/28] Simplify flush check sum array initialisation. --- src/Constants.h | 4 ++-- src/SevenEval.cpp | 12 ++++++------ 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src/Constants.h b/src/Constants.h index 9e6d3c0..b363933 100644 --- a/src/Constants.h +++ b/src/Constants.h @@ -91,8 +91,8 @@ #define CIRCUMFERENCE_SEVEN 4565145 // Used in flush checking. These must be distinct from each of the suits. -#define UNVERIFIED -2 -#define NOT_A_FLUSH -1 +#define UNVERIFIED -1 +#define NOT_A_FLUSH -2 // Bit masks #define SUIT_BIT_MASK 511 diff --git a/src/SevenEval.cpp b/src/SevenEval.cpp index 9a03c1d..5061a20 100644 --- a/src/SevenEval.cpp +++ b/src/SevenEval.cpp @@ -1,5 +1,6 @@ #include "SevenEval.h" #include "FiveEval.h" +#include SevenEval::SevenEval() : mRankPtr(new short unsigned[CIRCUMFERENCE_SEVEN]), mFlushRankPtr(new short unsigned[MAX_SEVEN_FLUSH_KEY_INT+1]) { @@ -132,12 +133,11 @@ SevenEval::SevenEval() : mRankPtr(new short unsigned[CIRCUMFERENCE_SEVEN]), short suit_count = 0, flush_suit_index = -1, cards_matched_so_far = 0; short suit_key = SPADE; short const suits[4] = {SPADE, HEART, DIAMOND, CLUB}; - - // Initialise all entries of mFlushCheck[] to UNVERIFIED, as yet unchecked. - for (int i = 0 ; i < MAX_FLUSH_CHECK_SUM+1; ++i) { - mFlushCheck[i] = UNVERIFIED; - } - + + // Initialise all entries of mFlushCheck to UNVERIFIED, as yet unchecked. + memset(mFlushCheck, UNVERIFIED, + sizeof(mFlushCheck[0]) * (MAX_FLUSH_CHECK_SUM+1)); + // Seven-card flush. for (int i = 0; i < NUMBER_OF_SUITS; ++i) { for (int j = 0; j <= i; ++j) { From 352e5abbf23cb11275e1a1bba30cd04498fb91d3 Mon Sep 17 00:00:00 2001 From: Ken Shackleton Date: Sat, 10 Sep 2016 08:51:12 +0100 Subject: [PATCH 27/28] Only add when the card matches the flush suit. --- src/SevenEval.cpp | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/SevenEval.cpp b/src/SevenEval.cpp index 5061a20..b01deb0 100644 --- a/src/SevenEval.cpp +++ b/src/SevenEval.cpp @@ -200,14 +200,14 @@ short unsigned SevenEval::GetRank(int const i, int const j, int const k, key - CIRCUMFERENCE_SEVEN)]; } // Generate a flush key, and look up the rank. - int const flush_key = - (mDeckcardsSuit[i] == flush_suit ? mDeckcardsFlush[i] : 0) + - (mDeckcardsSuit[j] == flush_suit ? mDeckcardsFlush[j] : 0) + - (mDeckcardsSuit[k] == flush_suit ? mDeckcardsFlush[k] : 0) + - (mDeckcardsSuit[l] == flush_suit ? mDeckcardsFlush[l] : 0) + - (mDeckcardsSuit[m] == flush_suit ? mDeckcardsFlush[m] : 0) + - (mDeckcardsSuit[n] == flush_suit ? mDeckcardsFlush[n] : 0) + - (mDeckcardsSuit[p] == flush_suit ? mDeckcardsFlush[p] : 0); + int flush_key = 0; + if (mDeckcardsSuit[i] == flush_suit) flush_key += mDeckcardsFlush[i]; + if (mDeckcardsSuit[j] == flush_suit) flush_key += mDeckcardsFlush[j]; + if (mDeckcardsSuit[k] == flush_suit) flush_key += mDeckcardsFlush[k]; + if (mDeckcardsSuit[l] == flush_suit) flush_key += mDeckcardsFlush[l]; + if (mDeckcardsSuit[m] == flush_suit) flush_key += mDeckcardsFlush[m]; + if (mDeckcardsSuit[n] == flush_suit) flush_key += mDeckcardsFlush[n]; + if (mDeckcardsSuit[p] == flush_suit) flush_key += mDeckcardsFlush[p]; return mFlushRankPtr[flush_key]; } From 2600bb7858af34047bd76fe2851346ed8c8b51ba Mon Sep 17 00:00:00 2001 From: Ken Date: Sat, 22 Oct 2016 17:22:30 +0100 Subject: [PATCH 28/28] Increase version number to 1.4. --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 83431f7..225cdef 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -5,7 +5,7 @@ project(${PROJECT_NAME}) # Versioning. set(SK_POKER_EVAL_VERSION_MAJOR 1) -set(SK_POKER_EVAL_VERSION_MINOR 3) +set(SK_POKER_EVAL_VERSION_MINOR 4) set(SK_POKER_EVAL_VERSION_PATCH 0) # Get the current commit.