/*
* eval.h: a fast poker hand evaluator
*
* Copyright (C) 1993-99 Brian Goetz, Keith Miyake, Clifford T. Matthews
*
* 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 toplevel directory called "GPLv3".
* If not, see .
*/
#ifndef __EVAL_H__
#define __EVAL_H__
#include "poker_defs.h"
#include
/*
* When run over seven cards, here are the distribution of hands:
* high hand: 23294460
* pair: 58627800
* two pair: 31433400
* three of a kind: 6461620
* straight: 6180020
* flush: 4047644
* full house: 3473184
* four of a kind: 224848
* straight flush: 41584
*
*/
#define SC sc
#define SD sd
#define SH sh
#define SS ss
/*
* is_straight used to check for a straight by masking the ranks with four
* copies of itself, each shifted one bit with respect to the
* previous one. So any sequence of five adjacent bits will still
* be non-zero, but any gap will result in a zero value. There's
* a nice side-effect of leaving the top most bit set so we can use
* it to set top_card.
* Now we use a precomputed lookup table.
*
*/
#if 0
/* Keith's is-straight, which is still pretty good and uses one less table. */
if ( (ranks2 = ranks & (ranks << 1)) &&
(ranks2 &= (ranks << 2)) &&
(ranks2 &= (ranks << 3)) &&
(ranks2 &= (ranks << 4)) ) {
retval.eval_t.hand = StdRules_HandType_STRAIGHT;
retval.eval_t.top_card = topCardTable[ranks2];
} else if ((ranks & StdDeck_FIVE_STRAIGHT) == StdDeck_FIVE_STRAIGHT) {
retval.eval_t.hand = StdRules_HandType_STRAIGHT;
retval.eval_t.top_card = StdDeck_Ranks_5;
}
#endif
static inline HandVal
StdDeck_StdRules_EVAL_N( StdDeck_CardMask cards, int n_cards )
{
HandVal retval;
uint32 ranks, four_mask, three_mask, two_mask,
n_dups, n_ranks;
uint32 sc, sd, sh, ss;
ss = StdDeck_CardMask_SPADES(cards);
sc = StdDeck_CardMask_CLUBS(cards);
sd = StdDeck_CardMask_DIAMONDS(cards);
sh = StdDeck_CardMask_HEARTS(cards);
retval = 0;
ranks = SC | SD | SH | SS;
n_ranks = nBitsTable[ranks];
n_dups = n_cards - n_ranks;
/* Check for straight, flush, or straight flush, and return if we can
determine immediately that this is the best possible hand
*/
if (n_ranks >= 5) {
if (nBitsTable[SS] >= 5) {
if (straightTable[SS])
return HandVal_HANDTYPE_VALUE(StdRules_HandType_STFLUSH)
+ HandVal_TOP_CARD_VALUE(straightTable[SS]);
else
retval = HandVal_HANDTYPE_VALUE(StdRules_HandType_FLUSH)
+ topFiveCardsTable[SS];
}
else if (nBitsTable[SC] >= 5) {
if (straightTable[SC])
return HandVal_HANDTYPE_VALUE(StdRules_HandType_STFLUSH)
+ HandVal_TOP_CARD_VALUE(straightTable[SC]);
else
retval = HandVal_HANDTYPE_VALUE(StdRules_HandType_FLUSH)
+ topFiveCardsTable[SC];
}
else if (nBitsTable[SD] >= 5) {
if (straightTable[SD])
return HandVal_HANDTYPE_VALUE(StdRules_HandType_STFLUSH)
+ HandVal_TOP_CARD_VALUE(straightTable[SD]);
else
retval = HandVal_HANDTYPE_VALUE(StdRules_HandType_FLUSH)
+ topFiveCardsTable[SD];
}
else if (nBitsTable[SH] >= 5) {
if (straightTable[SH])
return HandVal_HANDTYPE_VALUE(StdRules_HandType_STFLUSH)
+ HandVal_TOP_CARD_VALUE(straightTable[SH]);
else
retval = HandVal_HANDTYPE_VALUE(StdRules_HandType_FLUSH)
+ topFiveCardsTable[SH];
}
else {
int st;
st = straightTable[ranks];
if (st)
retval = HandVal_HANDTYPE_VALUE(StdRules_HandType_STRAIGHT)
+ HandVal_TOP_CARD_VALUE(st);
};
/* Another win -- if there can't be a FH/Quads (n_dups < 3),
which is true most of the time when there is a made hand, then if we've
found a five card hand, just return. This skips the whole process of
computing two_mask/three_mask/etc.
*/
if (retval && n_dups < 3)
return retval;
};
/*
* By the time we're here, either:
1) there's no five-card hand possible (flush or straight), or
2) there's a flush or straight, but we know that there are enough
duplicates to make a full house / quads possible.
*/
switch (n_dups)
{
case 0:
/* It's a no-pair hand */
return HandVal_HANDTYPE_VALUE(StdRules_HandType_NOPAIR)
+ topFiveCardsTable[ranks];
break;
case 1: {
/* It's a one-pair hand */
uint32 t, kickers;
two_mask = ranks ^ (SC ^ SD ^ SH ^ SS);
retval = HandVal_HANDTYPE_VALUE(StdRules_HandType_ONEPAIR)
+ HandVal_TOP_CARD_VALUE(topCardTable[two_mask]);
t = ranks ^ two_mask; /* Only one bit set in two_mask */
/* Get the top five cards in what is left, drop all but the top three
* cards, and shift them by one to get the three desired kickers */
kickers = (topFiveCardsTable[t] >> HandVal_CARD_WIDTH)
& ~HandVal_FIFTH_CARD_MASK;
retval += kickers;
return retval;
}
break;
case 2:
/* Either two pair or trips */
two_mask = ranks ^ (SC ^ SD ^ SH ^ SS);
if (two_mask) {
uint32 t;
t = ranks ^ two_mask; /* Exactly two bits set in two_mask */
retval = HandVal_HANDTYPE_VALUE(StdRules_HandType_TWOPAIR)
+ (topFiveCardsTable[two_mask]
& (HandVal_TOP_CARD_MASK | HandVal_SECOND_CARD_MASK))
+ HandVal_THIRD_CARD_VALUE(topCardTable[t]);
return retval;
}
else {
int t, second;
three_mask = (( SC&SD )|( SH&SS )) & (( SC&SH )|( SD&SS ));
retval = HandVal_HANDTYPE_VALUE(StdRules_HandType_TRIPS)
+ HandVal_TOP_CARD_VALUE(topCardTable[three_mask]);
t = ranks ^ three_mask; /* Only one bit set in three_mask */
second = topCardTable[t];
retval += HandVal_SECOND_CARD_VALUE(second);
t ^= (1 << second);
retval += HandVal_THIRD_CARD_VALUE(topCardTable[t]);
return retval;
}
break;
default:
/* Possible quads, fullhouse, straight or flush, or two pair */
four_mask = SH & SD & SC & SS;
if (four_mask) {
int tc;
tc = topCardTable[four_mask];
retval = HandVal_HANDTYPE_VALUE(StdRules_HandType_QUADS)
+ HandVal_TOP_CARD_VALUE(tc)
+ HandVal_SECOND_CARD_VALUE(topCardTable[ranks ^ (1 << tc)]);
return retval;
};
/* Technically, three_mask as defined below is really the set of
bits which are set in three or four of the suits, but since
we've already eliminated quads, this is OK */
/* Similarly, two_mask is really two_or_four_mask, but since we've
already eliminated quads, we can use this shortcut */
two_mask = ranks ^ (SC ^ SD ^ SH ^ SS);
if (nBitsTable[two_mask] != n_dups) {
/* Must be some trips then, which really means there is a
full house since n_dups >= 3 */
int tc, t;
three_mask = (( SC&SD )|( SH&SS )) & (( SC&SH )|( SD&SS ));
retval = HandVal_HANDTYPE_VALUE(StdRules_HandType_FULLHOUSE);
tc = topCardTable[three_mask];
retval += HandVal_TOP_CARD_VALUE(tc);
t = (two_mask | three_mask) ^ (1 << tc);
retval += HandVal_SECOND_CARD_VALUE(topCardTable[t]);
return retval;
};
if (retval) /* flush and straight */
return retval;
else {
/* Must be two pair */
int top, second;
retval = HandVal_HANDTYPE_VALUE(StdRules_HandType_TWOPAIR);
top = topCardTable[two_mask];
retval += HandVal_TOP_CARD_VALUE(top);
second = topCardTable[two_mask ^ (1 << top)];
retval += HandVal_SECOND_CARD_VALUE(second);
retval += HandVal_THIRD_CARD_VALUE(topCardTable[ranks ^ (1 << top)
^ (1 << second)]);
return retval;
};
break;
};
/* Should never happen */
assert(!"Logic error in StdDeck_StdRules_EVAL_N");
}
#undef SC
#undef SH
#undef SD
#undef SS
#endif