Skip to content

Commit

Permalink
Merge branch 'release/1.5'
Browse files Browse the repository at this point in the history
  • Loading branch information
kennethshackleton committed Nov 12, 2016
2 parents 28e7d26 + 429f5e3 commit 871bcf7
Show file tree
Hide file tree
Showing 14 changed files with 984 additions and 215 deletions.
2 changes: 2 additions & 0 deletions .gitignore
Expand Up @@ -18,4 +18,6 @@ build/
libskpokereval.a
lib
SKConfig.h
*.o


7 changes: 6 additions & 1 deletion CHANGELOG.md
@@ -1,5 +1,11 @@
### Change Log

#### 1.5.0

* Static interface.
* Include scripts for key generation and hashing.
* Include profiler.

#### 1.4.2

* CHM perfect hash of seven rank keys, optimisation that also reduces footprint.
Expand Down Expand Up @@ -31,4 +37,3 @@
#### 1.0

* Settle on publishing only in C++.

5 changes: 2 additions & 3 deletions CMakeLists.txt
Expand Up @@ -5,8 +5,8 @@ project(${PROJECT_NAME})

# Versioning.
set(SK_POKER_EVAL_VERSION_MAJOR 1)
set(SK_POKER_EVAL_VERSION_MINOR 4)
set(SK_POKER_EVAL_VERSION_PATCH 2)
set(SK_POKER_EVAL_VERSION_MINOR 5)
set(SK_POKER_EVAL_VERSION_PATCH 0)

# Get the current commit.
execute_process(
Expand Down Expand Up @@ -43,4 +43,3 @@ 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)

16 changes: 2 additions & 14 deletions README.md
@@ -1,32 +1,20 @@
# SKPokerEval

SKPokerEval is a lightweight 32-bit Texas Hold'em 5- and 7-card hand evaluator
written in C++.
A lightweight 32-bit Texas Hold'em 7-card hand evaluator written in C++.

## Travis status

[![Build Status](https://travis-ci.org/kennethshackleton/SKPokerEval.svg)](https://travis-ci.org/kennethshackleton/SKPokerEval)

## Build instructions

From the root directory of the project execute:

```
./configure && cmake . && make && ctest
```

This will build the library and run unit tests.

## Example

```
#include <iostream>
#include "SevenEval.h"
int main() {
SevenEval const eval;
// Get the rank of the seven-card spade flush, ace high.
std::cout << eval.GetRank(0, 4, 8, 12, 16, 20, 24) << std::endl;
 std::cout << SevenEval::GetRank(0, 4, 8, 12, 16, 20, 24) << std::endl;
return 0;
}
```
95 changes: 95 additions & 0 deletions scripts/perfect_hash.py
@@ -0,0 +1,95 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-

# SKPokerEval
#
# Copyright 2010 Kenneth J. Shackleton
#
# This program gives you software freedom; you can copy, convey, propagate,
# redistribute and/or modify this program under the terms of the GNU General
# Public License (GPL) as published by the Free Software Foundation (FSF),
# either version 3 of the License, or (at your option) any later version of
# the GPL published by the FSF.
#
# 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 in a file in the top-level directory called "GPLv3". If
# not, see http://www.gnu.org/licenses/.

# A Czech-Havas-Majewski perfect hash implementation.
# See "Fundamental Study Perfect Hashing" by Czech, Havas, Majewski,
# Theoretical Computer Science 182 (1997) 1-143.

val = [0, 1, 5, 22, 98, 453, 2031, 8698, 22854, 83661, 262349, 636345, 1479181]
keys = set([])
max_key = 0

for i in xrange(1, 13):
for j in xrange(1, i+1):
for k in xrange(1, j+1):
for l in xrange(0, k+1):
for m in xrange(0, l+1):
if not m < i:
break
for n in xrange(0, m+1):
if not n < j:
break
for p in xrange(0, n+1):
if not p < k:
break
key = val[i] + val[j] + val[k] + val[l] + val[m] +\
val[n] + val[p]
keys.add(key)
max_key = max(max_key, key)

print "Key count is %i." % (len(keys),)
print "Max key is %i." % (max_key,)

side = 1 # Power of 2 to ultimately optimise hash key calculation.
exp = 0
while side*side <= max_key:
side <<= 1
exp += 1

print "Square will be of side %i." % (side,)

square = [[-1]*side for i in xrange(side)]

for k in keys:
square[k & (side - 1)][k >> exp] = k

offset = [0]*((max_key / side) + 1)
hash_table = [-1]*max_key
hash_table_len = 0

for i in xrange(0, len(offset)):
for j in xrange(0, len(hash_table)-side):
collision = False
for k in xrange(0, side):
if hash_table[j+k] != -1 and square[k][i] != -1:
collision = True
break
if not collision:
offset[i] = j
for k in xrange(0, side):
x = square[k][i]
if x != -1:
hash_table[j+k] = x
hash_table_len = max(hash_table_len, j+side)
print "Offset of row %i is %i (length %i)." %\
(i, j, hash_table_len)
break

f = open('./hash_table', 'w')
f.write("%s\n" % (hash_table[0:hash_table_len],))
f.close()

f = open('./offset', 'w')
f.write("%s\n" % (offset,))
f.close()

print "Hash table has length %i." % (hash_table_len,)
70 changes: 70 additions & 0 deletions scripts/seven_key_gen.py
@@ -0,0 +1,70 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-

# SKPokerEval
#
# Copyright 2010 Kenneth J. Shackleton
#
# This program gives you software freedom; you can copy, convey, propagate,
# redistribute and/or modify this program under the terms of the GNU General
# Public License (GPL) as published by the Free Software Foundation (FSF),
# either version 3 of the License, or (at your option) any later version of
# the GPL published by the FSF.
#
# 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 in a file in the top-level directory called "GPLv3". If
# not, see http://www.gnu.org/licenses/.

# Script for generating the first 13 non-negative integers with the property
# that the sum of any seven with each appearing at most four times is always
# unique among all such sums.
#
# The output is:
# [0, 1, 5, 22, 98, 453, 2031, 8698, 22854, 83661, 262349, 636345, 1479181].

prime = [0, 1, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
sums = [0]*1000000
rank = [0]*1000000
K = 3
while K <= 12:
s = prime[K-1] + 1
accept = False
while not accept:
t = 0
accept = True
prime[K] = s
for i in xrange(0, K+1):
for j in xrange(i, K+1):
for k in xrange(j, K+1):
for l in xrange(k, K+1):
for m in xrange(l, K+1):
if m == i:
continue
for n in xrange(m, K+1):
if n == j:
continue
for p in xrange(n, K+1):
if p == k:
continue
sums[t] = prime[i] + prime[j] + prime[k] +\
prime[l] + prime[m] + prime[n] +\
prime[p]
t += 1
v = 0
while accept and v < t-1:
w = v + 1
while accept and w < t:
if sums[v] == sums[w]:
accept = False
w += 1
v += 1
if accept:
print prime
else:
s += 1
K += 1
2 changes: 0 additions & 2 deletions src/CMakeLists.txt
@@ -1,5 +1,3 @@
add_library(skpokereval
FiveEval.cpp
SevenEval.cpp
)

125 changes: 125 additions & 0 deletions src/Deckcards.h
@@ -0,0 +1,125 @@
// SKPokerEval
//
// Copyright 2010 Kenneth J. Shackleton
//
// This program gives you software freedom; you can copy, convey, propagate,
// redistribute and/or modify this program under the terms of the GNU General
// Public License (GPL) as published by the Free Software Foundation (FSF),
// either version 3 of the License, or (at your option) any later version of
// the GPL published by the FSF.
//
// 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 in a file in the top-level directory called "GPLv3". If
// not, see http://www.gnu.org/licenses/.

#ifndef SKPOKEREVAL_DECKCARDS_H
#define SKPOKEREVAL_DECKCARDS_H

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

uint32_t const card[DECK_SIZE] = {
(ACE << NON_FLUSH_BIT_SHIFT) + SPADE,
(ACE << NON_FLUSH_BIT_SHIFT) + HEART,
(ACE << NON_FLUSH_BIT_SHIFT) + DIAMOND,
(ACE << NON_FLUSH_BIT_SHIFT) + CLUB,

(KING << NON_FLUSH_BIT_SHIFT) + SPADE,
(KING << NON_FLUSH_BIT_SHIFT) + HEART,
(KING << NON_FLUSH_BIT_SHIFT) + DIAMOND,
(KING << NON_FLUSH_BIT_SHIFT) + CLUB,

(QUEEN << NON_FLUSH_BIT_SHIFT) + SPADE,
(QUEEN << NON_FLUSH_BIT_SHIFT) + HEART,
(QUEEN << NON_FLUSH_BIT_SHIFT) + DIAMOND,
(QUEEN << NON_FLUSH_BIT_SHIFT) + CLUB,

(JACK << NON_FLUSH_BIT_SHIFT) + SPADE,
(JACK << NON_FLUSH_BIT_SHIFT) + HEART,
(JACK << NON_FLUSH_BIT_SHIFT) + DIAMOND,
(JACK << NON_FLUSH_BIT_SHIFT) + CLUB,

(TEN << NON_FLUSH_BIT_SHIFT) + SPADE,
(TEN << NON_FLUSH_BIT_SHIFT) + HEART,
(TEN << NON_FLUSH_BIT_SHIFT) + DIAMOND,
(TEN << NON_FLUSH_BIT_SHIFT) + CLUB,

(NINE << NON_FLUSH_BIT_SHIFT) + SPADE,
(NINE << NON_FLUSH_BIT_SHIFT) + HEART,
(NINE << NON_FLUSH_BIT_SHIFT) + DIAMOND,
(NINE << NON_FLUSH_BIT_SHIFT) + CLUB,

(EIGHT << NON_FLUSH_BIT_SHIFT) + SPADE,
(EIGHT << NON_FLUSH_BIT_SHIFT) + HEART,
(EIGHT << NON_FLUSH_BIT_SHIFT) + DIAMOND,
(EIGHT << NON_FLUSH_BIT_SHIFT) + CLUB,

(SEVEN << NON_FLUSH_BIT_SHIFT) + SPADE,
(SEVEN << NON_FLUSH_BIT_SHIFT) + HEART,
(SEVEN << NON_FLUSH_BIT_SHIFT) + DIAMOND,
(SEVEN << NON_FLUSH_BIT_SHIFT) + CLUB,

(SIX << NON_FLUSH_BIT_SHIFT) + SPADE,
(SIX << NON_FLUSH_BIT_SHIFT) + HEART,
(SIX << NON_FLUSH_BIT_SHIFT) + DIAMOND,
(SIX << NON_FLUSH_BIT_SHIFT) + CLUB,

(FIVE << NON_FLUSH_BIT_SHIFT) + SPADE,
(FIVE << NON_FLUSH_BIT_SHIFT) + HEART,
(FIVE << NON_FLUSH_BIT_SHIFT) + DIAMOND,
(FIVE << NON_FLUSH_BIT_SHIFT) + CLUB,

(FOUR << NON_FLUSH_BIT_SHIFT) + SPADE,
(FOUR << NON_FLUSH_BIT_SHIFT) + HEART,
(FOUR << NON_FLUSH_BIT_SHIFT) + DIAMOND,
(FOUR << NON_FLUSH_BIT_SHIFT) + CLUB,

(THREE << NON_FLUSH_BIT_SHIFT) + SPADE,
(THREE << NON_FLUSH_BIT_SHIFT) + HEART,
(THREE << NON_FLUSH_BIT_SHIFT) + DIAMOND,
(THREE << NON_FLUSH_BIT_SHIFT) + CLUB,

(TWO << NON_FLUSH_BIT_SHIFT) + SPADE,
(TWO << NON_FLUSH_BIT_SHIFT) + HEART,
(TWO << NON_FLUSH_BIT_SHIFT) + DIAMOND,
(TWO << NON_FLUSH_BIT_SHIFT) + CLUB
};

uint16_t const suit[DECK_SIZE] = {
SPADE, HEART, DIAMOND, CLUB,
SPADE, HEART, DIAMOND, CLUB,
SPADE, HEART, DIAMOND, CLUB,
SPADE, HEART, DIAMOND, CLUB,
SPADE, HEART, DIAMOND, CLUB,
SPADE, HEART, DIAMOND, CLUB,
SPADE, HEART, DIAMOND, CLUB,
SPADE, HEART, DIAMOND, CLUB,
SPADE, HEART, DIAMOND, CLUB,
SPADE, HEART, DIAMOND, CLUB,
SPADE, HEART, DIAMOND, CLUB,
SPADE, HEART, DIAMOND, CLUB,
SPADE, HEART, DIAMOND, CLUB
};

uint16_t const flush[DECK_SIZE] = {
ACE_FLUSH, ACE_FLUSH, ACE_FLUSH, ACE_FLUSH,
KING_FLUSH, KING_FLUSH, KING_FLUSH, KING_FLUSH,
QUEEN_FLUSH, QUEEN_FLUSH, QUEEN_FLUSH, QUEEN_FLUSH,
JACK_FLUSH, JACK_FLUSH, JACK_FLUSH, JACK_FLUSH,
TEN_FLUSH, TEN_FLUSH, TEN_FLUSH, TEN_FLUSH,
NINE_FLUSH, NINE_FLUSH, NINE_FLUSH, NINE_FLUSH,
EIGHT_FLUSH, EIGHT_FLUSH, EIGHT_FLUSH, EIGHT_FLUSH,
SEVEN_FLUSH, SEVEN_FLUSH, SEVEN_FLUSH, SEVEN_FLUSH,
SIX_FLUSH, SIX_FLUSH, SIX_FLUSH, SIX_FLUSH,
FIVE_FLUSH, FIVE_FLUSH, FIVE_FLUSH, FIVE_FLUSH,
FOUR_FLUSH, FOUR_FLUSH, FOUR_FLUSH, FOUR_FLUSH,
THREE_FLUSH, THREE_FLUSH, THREE_FLUSH, THREE_FLUSH,
TWO_FLUSH, TWO_FLUSH, TWO_FLUSH, TWO_FLUSH
};

#endif

0 comments on commit 871bcf7

Please sign in to comment.