You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
644 lines
18 KiB
644 lines
18 KiB
// from http://www.azillionmonkeys.com/qed/poker.zip
|
|
// shamelessly copied from azillionmonkeys. getting millions of evals per second!
|
|
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include <stdint.h>
|
|
#include <time.h>
|
|
#include <unistd.h>
|
|
|
|
#define CLUB_SUIT (1)
|
|
#define DIAMOND_SUIT (2)
|
|
#define HEART_SUIT (4)
|
|
#define SPADE_SUIT (8)
|
|
|
|
#define RANK_SHL (27)
|
|
#define SUBR_SHL (13)
|
|
#define SUBR_SHLMASK ((1<<SUBR_SHL)-1)
|
|
|
|
#define STRAIGHT_FLUSH_SCORE (8 << RANK_SHL)
|
|
#define FOUR_KIND_SCORE (7 << RANK_SHL)
|
|
#define FULL_HOUSE_SCORE (6 << RANK_SHL)
|
|
#define FLUSH_SCORE (5 << RANK_SHL)
|
|
#define STRAIGHT_SCORE (4 << RANK_SHL)
|
|
#define THREE_KIND_SCORE (3 << RANK_SHL)
|
|
#define TWO_PAIR_SCORE (2 << RANK_SHL)
|
|
#define TWO_KIND_SCORE (1 << RANK_SHL)
|
|
|
|
#define ONE_PAIR_SCORE (TWO_KIND_SCORE)
|
|
|
|
typedef uint8_t u8;
|
|
typedef int8_t s8;
|
|
typedef uint32_t u32;
|
|
typedef int32_t s32;
|
|
|
|
typedef struct { int32_t len; u8 entry[52]; } CardPileType;
|
|
|
|
static char *handstrs[16] = { "high card", "one pair", "two pair", "three of a kind", "straight", "flush", "full house", "four of a kind", "straight flush", "err", "err", "err", "err", "err", "err", "err" };
|
|
static char *kickerstrs[16] = { "", "kickers", "kicker", "kickers", "high", "high", "full of", "kicker", "high", "err", "err", "err", "err", "err", "err", "err" };
|
|
|
|
static u32 CardValue[52] = {
|
|
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12,
|
|
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12,
|
|
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12,
|
|
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12
|
|
};
|
|
|
|
static u32 CardSuit[52] = {
|
|
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
|
|
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
|
|
4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
|
|
8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8
|
|
};
|
|
|
|
int32_t cardstr(char *cardstr,uint8_t card)
|
|
{
|
|
int32_t suit; char *cardc = "A234567890JQK",suitc[4] = { 'C', 'D', 'H', 'S' };
|
|
suit = card / 13;
|
|
card %= 13;
|
|
if ( card == 9 )
|
|
sprintf(cardstr,"10%c",suitc[suit]);
|
|
else sprintf(cardstr,"%c%c",cardc[card],suitc[suit]);
|
|
return(card);
|
|
}
|
|
|
|
static u32 CardSuitIdx[52] = {
|
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
|
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
|
|
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
|
|
3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3
|
|
};
|
|
|
|
static u32 CardMask[52] = {
|
|
1, 2, 4, 8, 0x10, 0x20, 0x40, 0x80, 0x100, 0x200, 0x400, 0x800, 0x1000,
|
|
1, 2, 4, 8, 0x10, 0x20, 0x40, 0x80, 0x100, 0x200, 0x400, 0x800, 0x1000,
|
|
1, 2, 4, 8, 0x10, 0x20, 0x40, 0x80, 0x100, 0x200, 0x400, 0x800, 0x1000,
|
|
1, 2, 4, 8, 0x10, 0x20, 0x40, 0x80, 0x100, 0x200, 0x400, 0x800, 0x1000
|
|
};
|
|
|
|
static u32 FiveCardDrawScoreFast (u32 c0, u32 c1, u32 c2, u32 c3, u32 c4, u32 u)
|
|
{
|
|
u32 y,z,m1,m2,m3,m4;
|
|
// Test for single suitedness
|
|
u = u & (u - 1);
|
|
// Build masks of 1, 2, 3, and 4 of a kind.
|
|
m1 = c0 | c1;
|
|
m2 = c1 & c0;
|
|
|
|
m2 |= c2 & m1;
|
|
m1 |= c2;
|
|
|
|
m2 |= c3 & m1;
|
|
m1 |= c3;
|
|
|
|
m2 |= c4 & m1;
|
|
m1 |= c4;
|
|
|
|
if (m2 == 0) { // No pairs?
|
|
// Is the mask a sequence of 1 bits?
|
|
z = m1 & (m1 - 1);
|
|
z ^= m1;
|
|
y = (z << 5) - z;
|
|
// Deal with the bicycle/wheel 5,4,3,2,Ace straight
|
|
if (m1 == 0x100F) {
|
|
if (u != 0) return STRAIGHT_SCORE + 0xF;
|
|
return STRAIGHT_FLUSH_SCORE + 0xF;
|
|
}
|
|
if (y == m1) {
|
|
if (u != 0) return STRAIGHT_SCORE + m1;
|
|
return STRAIGHT_FLUSH_SCORE + m1;
|
|
}
|
|
if (u != 0) return m1; // Nothing
|
|
return FLUSH_SCORE + m1;
|
|
}
|
|
/*
|
|
// m1 = c0 | ... | c4
|
|
// m2 = (c0 & c1) | ((c0|c1) & c2) | ((c0|c1|c2) & c3) | ((c0|c1|c2|c3) & c4)
|
|
// m3 = mask of 3 or 4 of a kind.
|
|
// m4 = mask of 4 of a kind.
|
|
*/
|
|
m1 = c0 | c1;
|
|
m2 = c1 & c0;
|
|
|
|
m3 = c2 & m2;
|
|
m2 |= c2 & m1;
|
|
m1 |= c2;
|
|
|
|
m4 = c3 & m3;
|
|
m3 |= c3 & m2;
|
|
m2 |= c3 & m1;
|
|
m1 |= c3;
|
|
|
|
m4 |= c4 & m3;
|
|
m3 |= c4 & m2;
|
|
m2 |= c4 & m1;
|
|
m1 |= c4;
|
|
|
|
m1 &= ~m2;
|
|
if (m3 == 0) {
|
|
if ((m2 & (m2 - 1)) == 0)
|
|
return TWO_KIND_SCORE + (m2 << SUBR_SHL) + m1;
|
|
return TWO_PAIR_SCORE + (m2 << SUBR_SHL) + m1;
|
|
}
|
|
m2 &= ~m3;
|
|
if (m4 == 0) {
|
|
if (m2 == 0)
|
|
return THREE_KIND_SCORE + (m3 << SUBR_SHL) + m1;
|
|
return FULL_HOUSE_SCORE + (m3 << SUBR_SHL) + m2;
|
|
}
|
|
return FOUR_KIND_SCORE + (m4 << SUBR_SHL) + m1;
|
|
}
|
|
|
|
static u32 FiveCardDrawScore (const u8 * h)
|
|
{
|
|
u32 c0, c1, c2, c3, c4,u;
|
|
// Make suits powers of two.
|
|
u = CardSuit[h[0]];
|
|
u |= CardSuit[h[1]];
|
|
u |= CardSuit[h[2]];
|
|
u |= CardSuit[h[3]];
|
|
u |= CardSuit[h[4]];
|
|
// Make cards powers of two.
|
|
c0 = CardMask[h[0]];
|
|
c1 = CardMask[h[1]];
|
|
c2 = CardMask[h[2]];
|
|
c3 = CardMask[h[3]];
|
|
c4 = CardMask[h[4]];
|
|
return FiveCardDrawScoreFast (c0, c1, c2, c3, c4, u);
|
|
}
|
|
|
|
static u32 SevenCardDrawFlush (const u8 * h, const u32 c[7])
|
|
{
|
|
static s32 LG2TAB[9] = {-1, 0, 1, -1, 2, -1, -1, -1, 3};
|
|
u32 i,t,f[4]; s32 cc[4],s;
|
|
// Make suits powers of two.
|
|
// There is at most one flush in a 7 card hand. So up to 4 masks arecreated, each being the set of cards in one particular suit.
|
|
// As themasks are created a maximum countdown from 4 is tracked.
|
|
#if 0
|
|
s = (((((u32 *) h)[1])) * 5) & 0x00C0C0C0;
|
|
i = (((((u32 *) h)[0])) * 5) & 0xC0C0C0C0;
|
|
s = ((s * (1 + 64 + 4096)) >> 8) & 0x3F00;
|
|
i = ((i * (1 + 64 + 4096 + 262144)) >> 24) | s;
|
|
#endif
|
|
|
|
f[0] = f[1] = f[2] = f[3] = 0;
|
|
cc[0] = cc[1] = cc[2] = cc[3] = 4;
|
|
|
|
i = CardSuitIdx[h[0]];
|
|
f[i] = c[0]; cc[i]--;
|
|
|
|
i = CardSuitIdx[h[1]];
|
|
f[i] |= c[1]; cc[i]--;
|
|
|
|
i = CardSuitIdx[h[2]];
|
|
f[i] |= c[2]; cc[i]--;
|
|
|
|
i = CardSuitIdx[h[3]];
|
|
f[i] |= c[3]; cc[i]--;
|
|
|
|
i = CardSuitIdx[h[4]];
|
|
f[i] |= c[4]; cc[i]--;
|
|
|
|
i = CardSuitIdx[h[5]];
|
|
f[i] |= c[5]; cc[i]--;
|
|
|
|
i = CardSuitIdx[h[6]];
|
|
f[i] |= c[6]; cc[i]--;
|
|
|
|
// If any of the counts goes below 0, then that suit has at least 5 cards in it.
|
|
|
|
if (((cc[0] | cc[1]) | (cc[2] | cc[3])) < 0) {
|
|
|
|
// Map the negative count (of which there is at most 1) to the suit index.
|
|
|
|
s = (((cc[0] & 8) | (cc[1] & 16)) | ((cc[2] & 32) | (cc[3] & 64))) >> 3;
|
|
s = LG2TAB[s];
|
|
|
|
// Work out the top 5 cards, so that the proper flush is also known ...
|
|
|
|
t = f[s];
|
|
while (cc[s] < -1) {
|
|
t &= t - 1; // Rip off last bit.
|
|
cc[s]++;
|
|
}
|
|
|
|
// ... but also keep the low part so that all straight flushes can still be tested for.
|
|
|
|
return f[s] | (t << SUBR_SHL);
|
|
}
|
|
// 0 -> indicates there is no flush in the hand.
|
|
return 0;
|
|
}
|
|
|
|
#define SevenCardDrawFlushScore(f) (FLUSH_SCORE + ((f) >> SUBR_SHL))
|
|
|
|
u32 SevenCardDrawScore (const u8 * h)
|
|
{
|
|
u32 c[7],f, t, s, u, v,m1, m2, m3, m4;
|
|
c[0] = CardMask[h[0]];
|
|
c[1] = CardMask[h[1]];
|
|
c[2] = CardMask[h[2]];
|
|
c[3] = CardMask[h[3]];
|
|
c[4] = CardMask[h[4]];
|
|
c[5] = CardMask[h[5]];
|
|
c[6] = CardMask[h[6]];
|
|
// Work out flush mask always, since its only redundant in the case of a full house or 4 of a kind.
|
|
f = SevenCardDrawFlush (h, c);
|
|
// t is the full card mask
|
|
t = ((c[0] | c[1]) | (c[2] | c[3])) | (c[4] | c[5] | c[6]);
|
|
// If 7 cards are found in a row ...
|
|
s = t & (t - 1);
|
|
v = s ^ t;
|
|
u = (v << 7) - 1;
|
|
u &= ~(u >> 7);
|
|
// ... then work out the possible straight flush/bicycle, straight, and flush possibilities.
|
|
if ((u & t) == u) {
|
|
if (f) {
|
|
// Intersect the flush mask with the straight mask to try to figure out if we have a straight flush.
|
|
s = f & u;
|
|
u = s & (s - 1);
|
|
u ^= s;
|
|
u = (u << 7) - 1;
|
|
u &= ~(u >> 5);
|
|
t = u >> 1;
|
|
v = u >> 2;
|
|
if ((u & s) == u) return STRAIGHT_FLUSH_SCORE + u;
|
|
if ((t & s) == t) return STRAIGHT_FLUSH_SCORE + t;
|
|
if ((v & s) == v) return STRAIGHT_FLUSH_SCORE + v;
|
|
// Deal with possible bicycle/wheel 5,4,3,2,Ace straight flush
|
|
if ((0x100F & f) == 0x100F)
|
|
return STRAIGHT_FLUSH_SCORE + 0xF;
|
|
return SevenCardDrawFlushScore (f);
|
|
}
|
|
u &= ~(u >> 5);
|
|
return STRAIGHT_SCORE + u;
|
|
}
|
|
// If at most 6 cards are found in a row ...
|
|
u = (v << 6) - 1;
|
|
u &= ~(u >> 6);
|
|
if ((u & t) != u) {
|
|
u = s & (s - 1);
|
|
u ^= s;
|
|
u = (u << 6) - 1;
|
|
u &= ~(u >> 6);
|
|
}
|
|
// ... then work out the possible straight flush/bicycle, straight, and flush possibilities.
|
|
if ((u & t) == u) {
|
|
if (f) {
|
|
s = f & u;
|
|
u = s & (s - 1);
|
|
u ^= s;
|
|
u = (u << 6) - 1;
|
|
u &= ~(u >> 5);
|
|
t = u >> 1;
|
|
if ((u & s) == u) return STRAIGHT_FLUSH_SCORE + u;
|
|
if ((t & s) == t) return STRAIGHT_FLUSH_SCORE + t;
|
|
// Deal with possible bicycle/wheel 5,4,3,2,Ace straight flush
|
|
if ((0x100F & f) == 0x100F)
|
|
return STRAIGHT_FLUSH_SCORE + 0xF;
|
|
return SevenCardDrawFlushScore (f);
|
|
}
|
|
u &= ~(u >> 5);
|
|
return STRAIGHT_SCORE + u;
|
|
}
|
|
// If at most 5 cards are found in a row ...
|
|
u = (v << 5) - 1;
|
|
u &= ~(u >> 5);
|
|
if ((u & t) != u) {
|
|
v = s;
|
|
s = s & (s - 1);
|
|
v ^= s;
|
|
u = (v << 5) - 1;
|
|
u &= ~(u >> 5);
|
|
if ((u & t) != u) {
|
|
u = s & (s - 1);
|
|
s ^= u;
|
|
u = (s << 5) - 1;
|
|
u &= ~(u >> 5);
|
|
}
|
|
}
|
|
// ... then work out the possible straight flush/bicycle, straight, and flush possibilities.
|
|
if ((u & t) == u) {
|
|
if (f) {
|
|
s = f & u;
|
|
u = s & (s - 1);
|
|
u ^= s;
|
|
u = (u << 5) - 1;
|
|
u &= ~(u >> 5);
|
|
if ((u & s) == u) {
|
|
return STRAIGHT_FLUSH_SCORE + u;
|
|
}
|
|
// Deal with possible bicycle/wheel 5,4,3,2,Ace straight flush
|
|
if ((0x100F & f) == 0x100F)
|
|
return STRAIGHT_FLUSH_SCORE + 0xF;
|
|
return SevenCardDrawFlushScore (f);
|
|
}
|
|
u &= ~(u >> 5);
|
|
return STRAIGHT_SCORE + u;
|
|
}
|
|
// Deal with the bicycle/wheel 5,4,3,2,Ace straight
|
|
if ((0x100F & t) == 0x100F) {
|
|
if (f)
|
|
{
|
|
if ((0x100F & f) == 0x100F)
|
|
return STRAIGHT_FLUSH_SCORE + 0xF;
|
|
return SevenCardDrawFlushScore (f);
|
|
}
|
|
return STRAIGHT_SCORE + 0xF;
|
|
}
|
|
/*
|
|
// m1 = c0 | ... | c4
|
|
// m2 = (c0 & c1) | ((c0|c1) & c2) | ((c0|c1|c2) & c3) | ((c0|c1|c2|c3) & c4)
|
|
// m3 = mask of 3 or 4 of a kind.
|
|
// m4 = mask of 4 of a kind.
|
|
*/
|
|
|
|
m1 = c[0] | c[1];
|
|
m2 = c[1] & c[0];
|
|
|
|
m3 = c[2] & m2;
|
|
m2 |= c[2] & m1;
|
|
m1 |= c[2];
|
|
|
|
m4 = c[3] & m3;
|
|
m3 |= c[3] & m2;
|
|
m2 |= c[3] & m1;
|
|
m1 |= c[3];
|
|
|
|
m4 |= c[4] & m3;
|
|
m3 |= c[4] & m2;
|
|
m2 |= c[4] & m1;
|
|
m1 |= c[4];
|
|
|
|
m4 |= c[5] & m3;
|
|
m3 |= c[5] & m2;
|
|
m2 |= c[5] & m1;
|
|
m1 |= c[5];
|
|
|
|
m4 |= c[6] & m3;
|
|
m3 |= c[6] & m2;
|
|
m2 |= c[6] & m1;
|
|
m1 |= c[6];
|
|
// Make sure the m1 is just the mask of singleton cards.
|
|
m1 &= ~m2;
|
|
// No 3 or 4 of a kinds.
|
|
if (m3 == 0) {
|
|
if (f) {
|
|
return SevenCardDrawFlushScore (f);
|
|
}
|
|
if (m2) {
|
|
s = m2 & (m2 - 1);
|
|
if (s == 0) {
|
|
t = m1 & (m1 - 1);
|
|
t &= (t - 1);
|
|
return TWO_KIND_SCORE + (m2 << SUBR_SHL) + t;
|
|
}
|
|
v = m1;
|
|
t = s & (s - 1);
|
|
if (t) {
|
|
v |= m2 ^ s;
|
|
m2 = s;
|
|
} else {
|
|
v &= (v - 1);
|
|
}
|
|
v &= (v - 1);
|
|
return TWO_PAIR_SCORE + (m2 << SUBR_SHL) + v;
|
|
}
|
|
// Nothing -- just remove the two low cards.
|
|
m1 &= (m1 - 1);
|
|
m1 &= (m1 - 1);
|
|
return m1;
|
|
}
|
|
// 4 of a kind.
|
|
if (m4) {
|
|
m1 |= (m2 & ~m4);
|
|
while ((m2 = (m1 & (m1 - 1))) != 0) {
|
|
m1 = m2;
|
|
}
|
|
return FOUR_KIND_SCORE + (m4 << SUBR_SHL) + m1;
|
|
}
|
|
// 3 of a kind, but no other pair in the hand
|
|
if ((m2 & ~m3) == 0) {
|
|
t = m3 & (m3 - 1);
|
|
// Two 3 of a kinds => Full House
|
|
if (t)
|
|
return FULL_HOUSE_SCORE + (t << SUBR_SHL) + (m3 ^ t);
|
|
if (f)
|
|
return SevenCardDrawFlushScore (f);
|
|
// Just remove the two low cards, and score this as 3 of a kind.
|
|
m1 &= (m1 - 1);
|
|
m1 &= (m1 - 1);
|
|
return THREE_KIND_SCORE + (m3 << SUBR_SHL) + m1;
|
|
}
|
|
// 3 of a kind and a seperate 2 of a kind (full house.)
|
|
m2 &= ~m3;
|
|
t = m2 & (m2 - 1);
|
|
// If there are two 2 pairs in the hand, then pick the higher pair
|
|
if (!t) t = m2;
|
|
return FULL_HOUSE_SCORE + (m3 << SUBR_SHL) + t;
|
|
}
|
|
|
|
// Just a brute force 7 card draw ranking by picking each of the possible two cards to be skipped, and finding the score which is highest amongst the 21 possible 5 card sub-hands.
|
|
u32 SevenCardDrawScoreSlow (const u8 * h) {
|
|
s32 i, j, k;
|
|
u32 r, m;
|
|
u8 h2[5];
|
|
|
|
m = 0;
|
|
for (i=0; i < 6; i++) {
|
|
for (k=0; k < i; k++) {
|
|
h2[k] = h[k];
|
|
}
|
|
for (j=i+1; j < 7; j++) {
|
|
for (k=i+1; k < j; k++) {
|
|
h2[k-1] = h[k];
|
|
}
|
|
for (k=j+1; k < 7; k++) {
|
|
h2[k-2] = h[k];
|
|
}
|
|
r = FiveCardDrawScore (h2);
|
|
if (r > m) m = r;
|
|
}
|
|
}
|
|
return m;
|
|
}
|
|
|
|
// A correctly distributed (ignoring the problem of using "rand() % x") reshuffling of your cards.
|
|
static void Shuffle (CardPileType * c)
|
|
{
|
|
int32_t i, j, k; u8 t;
|
|
for (i = 0; i < (c->len - 1); i++)
|
|
{
|
|
k = (RAND_MAX / (c->len - i)) * (c->len - i);
|
|
do {
|
|
j = rand ();
|
|
} while (j >= k);
|
|
j = i + (j % (c->len - i));
|
|
t = c->entry[i];
|
|
c->entry[i] = c->entry[j];
|
|
c->entry[j] = t;
|
|
}
|
|
}
|
|
|
|
static int32_t Deal (CardPileType * h, CardPileType * d, int32_t n)
|
|
{
|
|
int32_t i;
|
|
for (i=0; i < n && d->len > 0; i++)
|
|
{
|
|
d->len--;
|
|
h->entry[ h->len ] = d->entry[ d->len ];
|
|
h->len++;
|
|
}
|
|
return i;
|
|
}
|
|
|
|
static void InitDeck (CardPileType * deck)
|
|
{
|
|
u8 i;
|
|
deck->len = 52;
|
|
for (i=0; i < 52; i++) deck->entry[i] = i;
|
|
}
|
|
|
|
static void DisplayCard (u8 c, char out[])
|
|
{
|
|
// char suitdisp[9] = { 0, 5, 4, 0, 3, 0, 0, 0, 6 };
|
|
static char suitdisp[9] = { 0, 'c', 'd', 0, 'h', 0, 0, 0, 's' };
|
|
char s[4];
|
|
s[0] = " 1 "[CardValue[c]];
|
|
s[1] = "234567890JQKA"[CardValue[c]];
|
|
s[2] = suitdisp[CardSuit[c]];
|
|
s[3] = '\0';
|
|
strcat (out, " ");
|
|
strcat (out, s);
|
|
}
|
|
|
|
void DisplayHand5 (const CardPileType * h) {
|
|
char out[128];
|
|
int i;
|
|
|
|
out[0] = '\0';
|
|
for (i=0; i < 5; i++) DisplayCard (h->entry[i], out);
|
|
sprintf (out + strlen (out), " => %08X\n", (int)FiveCardDrawScore (&h->entry[0]));
|
|
printf ("%s", out);
|
|
}
|
|
|
|
void set_cardstr(char *cardstr,uint32_t c)
|
|
{
|
|
/*static char suitdisp[9] = { 0, 'c', 'd', 0, 'h', 0, 0, 0, 's' };
|
|
cardstr[0] = " 1 "[CardValue[c % 13]];
|
|
cardstr[1] = "234567890JQKA"[CardValue[c % 13]];
|
|
cardstr[2] = suitdisp[CardSuit[c]];
|
|
cardstr[3] = '\0';*/
|
|
|
|
int32_t i,j=0;
|
|
c >>= 1;
|
|
for (i=12; i>=0; i--)
|
|
if ( ((1 << i) & c) != 0 )
|
|
{
|
|
cardstr[j++] = " 1 "[i];
|
|
cardstr[j++] = "234567890JQKA"[i];
|
|
cardstr[j++] = ' ';
|
|
}
|
|
cardstr[j++] = 0;
|
|
}
|
|
|
|
uint32_t set_handstr(char *handstr,uint8_t cards[7],int32_t verbose)
|
|
{
|
|
char cardstr[32],cardstr2[32],*kickerstr,*str; uint32_t score,i;
|
|
handstr[0] = 0;
|
|
if ( cards == 0 )
|
|
{
|
|
handstr[0] = 0;
|
|
printf("set_handstr: null cards??\n");
|
|
return(0);
|
|
}
|
|
for (i=0; i<7; i++)
|
|
if ( cards[i] < 0 || cards[i] >= 52 )
|
|
{
|
|
//printf("illegal card[%d] %d\n",i,cards[i]);
|
|
return(0);
|
|
}
|
|
score = SevenCardDrawScore (&cards[0]);
|
|
set_cardstr(cardstr,(score>>SUBR_SHL) & SUBR_SHLMASK);
|
|
set_cardstr(cardstr2,score & SUBR_SHLMASK);
|
|
kickerstr = kickerstrs[(score>>RANK_SHL)&15];
|
|
str = handstrs[(score>>RANK_SHL)&15];
|
|
if ( verbose != 0 )
|
|
{
|
|
if ( strcmp(kickerstr,"high") == 0 )
|
|
sprintf(handstr,"%c%c high %s",cardstr2[0],cardstr2[1],str);
|
|
else if ( strcmp(str,"full house") == 0 )
|
|
sprintf(handstr,"%c%c full of %c%c",cardstr[0],cardstr[1],cardstr2[0],cardstr2[1]);
|
|
else if ( strcmp(str,"three of a kind") == 0 )
|
|
sprintf(handstr,"set of %c%c with kickers %c%c %c%c",cardstr[0],cardstr[1],cardstr2[0],cardstr2[1],cardstr2[3],cardstr2[4]);
|
|
else if ( strcmp(str,"two pair") == 0 )
|
|
sprintf(handstr,"two pair %c%c and %c%c with %c%c kicker",cardstr[0],cardstr[1],cardstr[3],cardstr[4],cardstr2[0],cardstr2[1]);
|
|
else if ( strcmp(str,"one pair") == 0 )
|
|
sprintf(handstr,"pair of %c%c with %c%c kicker",cardstr[0],cardstr[1],cardstr2[0],cardstr2[1]);
|
|
else sprintf(handstr,"%s %s %s %s",str,cardstr,kickerstr,cardstr2);
|
|
}
|
|
else
|
|
{
|
|
if ( strcmp(kickerstr,"high") == 0 )
|
|
sprintf(handstr,"%c%c high %s",cardstr2[0],cardstr2[1],str);
|
|
else if ( strcmp(str,"full house") == 0 )
|
|
sprintf(handstr,"fullhouse %c%c %c%c",cardstr[0],cardstr[1],cardstr2[0],cardstr2[1]);
|
|
else if ( strcmp(str,"three of a kind") == 0 )
|
|
sprintf(handstr,"trip %c%c",cardstr[0],cardstr[1]);
|
|
else if ( strcmp(str,"two pair") == 0 )
|
|
sprintf(handstr,"two pairs %c%c %c%c",cardstr[0],cardstr[1],cardstr[3],cardstr[4]);
|
|
else if ( strcmp(str,"one pair") == 0 )
|
|
sprintf(handstr,"pair %c%c",cardstr[0],cardstr[1]);
|
|
else sprintf(handstr,"%s",cardstr2);
|
|
}
|
|
return(score);
|
|
}
|
|
|
|
void DisplayHand7(char *handstr,uint8_t *cards)
|
|
{
|
|
uint32_t x,y; int32_t i; char out[512];
|
|
out[0] = '\0';
|
|
for (i=0; i<7; i++)
|
|
DisplayCard (cards[i], out);
|
|
x = SevenCardDrawScore (cards);
|
|
y = SevenCardDrawScoreSlow (cards);
|
|
set_handstr(handstr,cards,1);
|
|
if ( x != y )
|
|
fprintf(stderr,"Error slow score %08x vs fast score %08x???\n",y,x);
|
|
sprintf (out + strlen (out), " => %08x %6d %6d -> (%s)",x,(x>>SUBR_SHL)&SUBR_SHLMASK,x&SUBR_SHLMASK,handstr);
|
|
printf("%s\n",out);
|
|
}
|
|
|
|
void poker_test()
|
|
{
|
|
char *_mbstr(double n);
|
|
CardPileType Deck,Hands[1000]; uint32_t c,starttime,score; uint64_t total,counter; char handstr[512]; uint8_t *cards;
|
|
//srand (0);
|
|
InitDeck (&Deck);
|
|
Shuffle (&Deck);
|
|
for (c=0; c<(sizeof(Hands)/sizeof(*Hands)); c++)
|
|
{
|
|
Deal (&Hands[c],&Deck,7);
|
|
DisplayHand7(handstr,Hands[c].entry);
|
|
Deal (&Deck,&Hands[c],7);
|
|
Shuffle(&Deck);
|
|
}
|
|
starttime = (uint32_t)time(NULL);
|
|
#ifndef _WIN32
|
|
while ( (uint32_t)time(NULL) == starttime )
|
|
usleep(100);
|
|
total = counter = 0;
|
|
while ( (uint32_t)time(NULL) < starttime+11 )
|
|
{
|
|
for (c=0; c<1000; c++,counter++)
|
|
{
|
|
cards = Hands[c % (sizeof(Hands)/sizeof(*Hands))].entry;
|
|
score = SevenCardDrawScore(cards);
|
|
total += score;
|
|
}
|
|
}
|
|
char *mbstr(char *str,double val);
|
|
char str[65]; printf("counter.%llu %s in 10 seconds: ave score %llx\n",(long long)counter,mbstr(str,counter),(long long)(total/counter));
|
|
#endif
|
|
}
|
|
|