// 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>
# 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
}