Sophie

Sophie

distrib > Mandriva > 2010.0 > i586 > media > contrib-release > by-pkgid > 2bb54e74e6dbbbfe00f09923014f5fe2 > files > 31

libpoker-eval-devel-135.0-1mdv2009.1.i586.rpm

/* DO NOT protect this file from multiple inclusions */

/*
 *  tree.h: The actual decision tree that new_eval.h uses
 *
 *  Copyright (C) 1994  Clifford T. Matthews
 *
 *  This package is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; version 2 dated June, 1991.
 *
 *  This package 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 package; if not, write to the Free Software
 *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
 *  MA 02110-1301, USA.
 */

/*
 * This file is included in multiple places in our new fast hand evaluator.
 * Each time it is included, certain hand identification predicate macros
 * are defined from outside this file, and then others are defined from
 * within this file, and then, using all the predicates, a decision tree is
 * walked until we get to a terminal node, at which point we return a complete
 * hand identifying value (i.e. a 32 bit number whose most significant bits
 * can be used to identify which type of hand you have (e.g. full-house), and
 * whose remaining bits can tell you the composition of the hand (e.g. sevens
 * and fives).
 *
 * In the interests of speed, we actually have three different types of
 * predicates.  The simplest either returns 0 or non-zero based on whether
 * or not the current hand is of a given type, given all the information
 * that we know by the time the predicate is called.  NOTE:  it is generally
 * NOT good computer science to have predicates that are postion dependent
 * (e.g. you can't use the TWO_PAIR_P predicate just anywhere in the below
 * code -- it can only be used after we've determined that we don't have
 * three of a kind).  However, it is faster to do things this way, and once
 * you fully understand what we're doing below, you can see that our code is
 * correct.  Simple predicates have names of the form XXX_P, where XXX is
 * the hand class in capital letters.  Simple predicates are ALWAYS defined
 * outside of this file (i.e. all the information that they need is available
 * to us at compile time).
 *
 * This file contains four types of things:
 *
 *      Complete predicate macros definitions that define macros which detect
 *      particular classes of hands and either return 0 if such a hand isn't
 *      detected, or a complete hand identifying value.  Complete predicate
 *      macros have names of the form XXX_complete_P, where XXX is the hand
 *      class in capital letters.
 *
 *      Helper predicate macro definitions that define macros which detect
 *      particular classes of hands and either return 0 if such a hand isn't
 *      detected, or a useful number which will be used later as the
 *      evaluation proceeds.  Helper predicate macros have names of the form
 *      XXX_helper_P, where XXX is the hand class in capital letters.
 *
 *      Helper macro definitions that aren't predicates, but that provide
 *      information useful to the tree walk.  Helper macros have names of
 *      the form YYY_helper, where YYY helps describe the data that the
 *      particular helper macro returns.
 *
 *      The decision tree code that uses all three classes of predicates to
 *      walk to the identifying node and then return the proper hand
 *      identifying value.  At different places, where this file is included
 *      some of the predicates that we #define below will be overridden with
 *      an outside definition of 0, because at compile time we can tell that
 *      certain hands do not need to be checked for particular hand types.
 *
 * The decision tree walking code frequently makes use of inline-functions
 * which map some intermediate information into coplete hand identifying
 * values.  These functions are defined elsewhere and have names of the
 * form lower_case_hand_class_value.
 *      
 */

/*
 * FLUSH_helper_P returns 0 if no flush, or the top 5 ranks in the flush suit
 *      if a flush is found.  We don't yet or in EvxHandVal_FLUSH, since that is
 *      premature.  We return what we do because it is all the information
 *      that is needed to continue checking for other things (like a straight
 *      flush).
 */

#if     !defined(FLUSH_helper_P)

#define FLUSH_helper_P()                                          \
    (evxFlushCardsTable[c] | evxFlushCardsTable[d]                  \
    | evxFlushCardsTable[h] | evxFlushCardsTable[s])

#endif

/*
 * STRAIGHT_FLUSH_helper_P returns 0 or a complete hand rank, but with the
 *      VALUE set as a straight value.  A straight flush is sufficiently rare
 *      that when we actually find one, we can clean up the VALUE by xoring in
 *      xor of the correct VALUE (i.e. EvxHandVal_STFLUSH) with the
 *      incorrect value (i.e. EvxHandVal_STRAIGHT).  Since a ^ (a^b) is b, this
 *      does the right thing and we don't need a separate table, which might
 *      slow us down by interfering with the data cache.
 */

#if     !defined(STRAIGHT_FLUSH_helper_P)

#define STRAIGHT_FLUSH_helper_P(suit)                                   \
    evxStrValueTable[suit]

#endif

#undef FK_LOCALS
#if     !defined(FOUR_OF_A_KIND_complete_P)

#define FOUR_OF_A_KIND_complete_P()                                     \
(   tmpFkRetval = c & d & h & s,                                        \
    tmpFkRetval?                                                        \
	EvxHandVal_QUADS | (tmpFkRetval << StdDeck_Rank_COUNT) |        \
			  	    topBitTable[ranks ^ tmpFkRetval]    \
      : tmpFkRetval                                                     \
)

#define FK_LOCALS uint32 tmpFkRetval;
#else
#define FK_LOCALS
#endif

/*
 * THREE_OF_A_KIND returns all the ranks that have at least three distinct
 *      members.  It is not sufficient to just return the top one, because
 *      of the splenderiferous implementation of FULL_HOUSE below.
 */

#if     !defined(THREE_OF_A_KIND_helper_P)

#define THREE_OF_A_KIND_helper_P()                                      \
     ((( c&d )|( h&s )) & (( c&h )|( d&s )))

#endif

/*
 * Watch closely:  FULL_HOUSE_complete_P will only be examined after we know
 *      that we do not have four of a kind.  So if we xor all four
 *      suits together we are left with ones every place where we
 *      either have one or three members of a particular rank.  If
 *      we invert this and then and it with ranks, we now only have
 *      ones where we have exactly two members of a particular
 *      rank.  However, this is not enough, because it is possible
 *      for a full-house to consist of two three-of-a-kinds, so we
 *      have to or in three_info, which contains all of our
 *      three-of-a-kinds.  Then we need to mask off the top rank
 *      to see if we still have a pair or three-of-a-kind left
 *      over.
 */

#undef FH_LOCALS
#if     !defined(FULL_HOUSE_complete_P)

#define FULL_HOUSE_complete_P(three_info)                               \
(   tmpFhRetval = (~(c^d^h^s) & ranks)|three_info,                      \
    tmpFhTopbit = topBitTable[three_info],                              \
    tmpFhRetval ^= tmpFhTopbit,                                         \
    tmpFhRetval?                                                        \
	EvxHandVal_FULLHOUSE | (tmpFhTopbit << StdDeck_Rank_COUNT) |    \
					topBitTable[tmpFhRetval]        \
    : tmpFhRetval                                                       \
)

#define FH_LOCALS uint32 tmpFhRetval, tmpFhTopbit;
#else
#define FH_LOCALS

#endif

#define STRAIGHT_FLUSH_XOR_CORRECTION_VALUE     (EvxHandVal_STRAIGHT ^       \
						EvxHandVal_STFLUSH)

#define ALL_PAIRS_helper()      (h & (d|c|s)) | (d & (c|s)) | (c & s)

{
  FK_LOCALS
  FH_LOCALS

    flush_suit = FLUSH_helper_P();
    if (STRAIGHT_P()) {
	if (flush_suit) {
	    if ((retval = STRAIGHT_FLUSH_helper_P(flush_suit))) {
		/* straight flush */
		return retval ^ STRAIGHT_FLUSH_XOR_CORRECTION_VALUE;
	    } else {
		if ((retval = FOUR_OF_A_KIND_complete_P())) {
		    return retval;
		    /* four of a kind */
		} else {
		    if ((three_info = THREE_OF_A_KIND_helper_P()) &&
			       (retval = FULL_HOUSE_complete_P(three_info))) {
			/* full house */
			return retval;
		    } else {
			/* flush */
			return flush_value(flush_suit);
		    }
		}
	    }
	} else {
	    if ((retval = FOUR_OF_A_KIND_complete_P())) {
		return retval;
		/* four of a kind */
	    } else {
		if ((three_info = THREE_OF_A_KIND_helper_P()) &&
			       (retval = FULL_HOUSE_complete_P(three_info))) {
		    /* full house */
		    return retval;
		} else {
		    /* straight */
		    return straight_value(ranks);
		}
	    }
	}
    } else {
	if (AT_LEAST_PAIR_P()) {
	    if ((three_info = THREE_OF_A_KIND_helper_P())) {
		if ((retval = FOUR_OF_A_KIND_complete_P())) {
		    return retval;
		    /* four of a kind */
		} else {
		    if ((retval = FULL_HOUSE_complete_P(three_info))) {
			/* full house */
			return retval;
		    } else {
			if (flush_suit) {
			    /* flush */
			    return flush_value(flush_suit);
			} else {
			    /* three of a kind */
			    return trips_value(ranks, three_info);
			}
		    }
		}
	    } else {
		if (flush_suit) {
		    /* flush */
		    return flush_value(flush_suit);
		} else {
		    all_pairs = ALL_PAIRS_helper();
		    if (PAIR_P()) {
			/* pair */
			return pair_value(ranks, all_pairs);
		    } else {
			/* two pair */
			return two_pair_value(ranks, all_pairs);
		    }
		}
	    }
	} else {
	    if (flush_suit) {
		/* flush */
		return flush_value(flush_suit);
	    } else {
		/* high hand */
		return nopair_value(ranks);
	    }
	}
    }
 }