Skip to content

Commit

Permalink
Merge branch 'release/1.4'
Browse files Browse the repository at this point in the history
  • Loading branch information
kennethshackleton committed Oct 22, 2016
2 parents 2267153 + 2600bb7 commit 8e42a44
Show file tree
Hide file tree
Showing 13 changed files with 486 additions and 90 deletions.
5 changes: 4 additions & 1 deletion .gitignore
Expand Up @@ -14,5 +14,8 @@ CTestTestfile.cmake
eval_tests

# Artifacts
libspecialkeval.a
build/
libskpokereval.a
lib
SKConfig.h

18 changes: 16 additions & 2 deletions .travis.yml
@@ -1,6 +1,20 @@
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;
cmake --version;
fi

script: ./build.sh

32 changes: 26 additions & 6 deletions CMakeLists.txt
@@ -1,26 +1,46 @@
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 4)
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"
"${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()
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/five_eval_tests.cpp tests/seven_eval_tests.cpp)
target_link_libraries(eval_tests gtest_main skpokereval)
add_test(NAME GTests COMMAND eval_tests)

3 changes: 3 additions & 0 deletions build.sh
@@ -0,0 +1,3 @@
#!/bin/sh
./configure && cmake . && make && ctest --verbose

5 changes: 5 additions & 0 deletions src/CMakeLists.txt
@@ -0,0 +1,5 @@
add_library(skpokereval
FiveEval.cpp
SevenEval.cpp
)

4 changes: 2 additions & 2 deletions src/Constants.h
Expand Up @@ -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
Expand Down
1 change: 1 addition & 0 deletions src/FiveEval.cpp
Expand Up @@ -187,3 +187,4 @@ short unsigned FiveEval::GetRank(int const card_one, int const card_two,
}
return best_rank_so_far;
}

6 changes: 2 additions & 4 deletions src/FiveEval.h
Expand Up @@ -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;
Expand Down
4 changes: 4 additions & 0 deletions 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@

112 changes: 53 additions & 59 deletions src/SevenEval.cpp
@@ -1,5 +1,6 @@
#include "SevenEval.h"
#include "FiveEval.h"
#include <cstring>

SevenEval::SevenEval() : mRankPtr(new short unsigned[CIRCUMFERENCE_SEVEN]),
mFlushRankPtr(new short unsigned[MAX_SEVEN_FLUSH_KEY_INT+1]) {
Expand All @@ -8,49 +9,49 @@ 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;
}

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) {
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) {
for (int m = 0; m <= l; ++m) {
for (int n = 0; n <= m; ++n) {
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 =
five_card_evaluator.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;
}
int const L = l<<2;
for (int m = 0; m <= l && m < i; ++m) {
int const M = (m<<2)+1;
for (int n = 0; n <= m && n < j; ++n) {
int const N = (n<<2)+1;
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];
// 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;
}
}
}
Expand All @@ -64,21 +65,19 @@ 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];
mFlushRankPtr[key] =
five_card_evaluator.GetRank(I, J, K, L, M, N, p<<2);
++count;
mFlushRankPtr[key] = eval.GetRank(I, J, K, L, M, N, p<<2);
}
}
}
Expand All @@ -102,10 +101,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.
mFlushRankPtr[key] =
five_card_evaluator.GetRank(I, J, K, L, M, n<<2, 51);
++count;
// all have the Spade suit.
mFlushRankPtr[key] = eval.GetRank(I, J, K, L, M, n<<2, 51);
}
}
}
Expand All @@ -125,8 +122,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);
++count;
mFlushRankPtr[key] = eval.GetRank(I, J, K, L, m<<2);
}
}
}
Expand All @@ -137,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) {
Expand Down Expand Up @@ -191,29 +186,28 @@ 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.
long 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.
int const flush_check_key = (const int) (key & SUIT_BIT_MASK);
short flush_suit = mFlushCheck[flush_check_key];
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)];
}
// 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];
}

16 changes: 8 additions & 8 deletions src/SevenEval.h
Expand Up @@ -20,6 +20,7 @@
#ifndef SKPOKEREVAL_SEVENEVAL_H
#define SKPOKEREVAL_SEVENEVAL_H

#include <cstdint>
#include "Constants.h"

class SevenEval {
Expand All @@ -29,15 +30,14 @@ 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;
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

0 comments on commit 8e42a44

Please sign in to comment.