Two Plus Two Newer Archives  

Go Back   Two Plus Two Newer Archives > Internet Gambling > Software

Reply
 
Thread Tools Display Modes
  #1  
Old 01-04-2007, 08:08 AM
RayW RayW is offline
Junior Member
 
Join Date: Mar 2005
Posts: 24
Default Re: 7 Card Hand Evaluators

Hi Juk!
[ QUOTE ]
I'm assuming the only benefit to using the perfect hash version faster lookup creation? (I just used Cactus Kev's source).

[/ QUOTE ]
Yes, the only reason I suggested Paul D. Senzee's Optimized Hand Evaluator was to keep the initial creation under a minute (and my debugging sanity [img]/images/graemlins/crazy.gif[/img])... You don't need it (you only run this once anyway).

[ QUOTE ]
PS: One other (unrelated) small thing I just worked out was how to get the code from within code-tags without losing all of the indentation: just hit "quote" and copy the text from within the edit box...

[/ QUOTE ]

Thank You for that Tip!! I was trying to figure out how to keep the formatting going on and coming out of this BBS. [img]/images/graemlins/blush.gif[/img]

Sounds like you are Blazin' so I guess the instructions weren't toooo bad!

Have a Profitable Day!
Ray...
Reply With Quote
  #2  
Old 01-04-2007, 03:37 PM
mykey1961 mykey1961 is offline
Senior Member
 
Join Date: Oct 2005
Posts: 249
Default Re: 7 Card Hand Evaluators

This is quite possibly the only time I've looked at someone else's code and knew what they were doing the whole way.

I like the additional vector [0] to give 5, and 6 card evaluations as well.

My code peaked out at 12.5 cycles. Since our access method is the same, I've got to believe the difference is due to my 10 year old compiler.
Reply With Quote
  #3  
Old 01-11-2007, 10:29 PM
mark007 mark007 is offline
Junior Member
 
Join Date: Jan 2007
Posts: 12
Default Re: 7 Card Hand Evaluators

Code thats blowing up on me so far
<font class="small">Code:</font><hr /><pre>
static long IDs[] = new long[612978];
static int numIDs = 1;
static long maxID = 0;
static int numcards = 0;
static int maxHR = 0;
static int HR[] = new int[32487834];
static int workcards[];
static int oldnumcards=1;

public static void main (String [] args)
{
doSetup();
}

public static int SaveID(long ID) {


if (ID == 0) return 0; // don't use up a record for a 0!

if (ID &gt;= maxID) { // take care of the most likely first goes on the end...
if (ID &gt; maxID) { // greater than create new else it was the last one!


IDs[numIDs++] = ID; // add the new ID
maxID = ID;
}
return numIDs - 1;
}

// find the slot I will find it (by a pseudo bsearch algorithm)
int low = 0;
int high = numIDs - 1;
long testval;
int holdtest;

while (high - low &gt; 1) {
holdtest = (high + low + 1) / 2;
testval = IDs[holdtest] - ID;
if (testval &gt; 0)
high = holdtest;
else if (testval &lt; 0)
low = holdtest;
else return holdtest; // got it!!
}
// I guess it couldn't be found so must be added to the current location (high)
// make space... // don't expect this much!

System.arraycopy(IDs,high,IDs,(high+1),(numIDs - high) );


IDs[high] = ID; // do the insert into the hole created

numIDs++;
return high;
}


public static long MakeID(long IDin, int newcard) // adding a new card to this ID
{

int suitcount[] = new int[4 + 1];
int rankcount[] = new int[13 + 1];
workcards = new int [8]; // intentially keeping one as a 0 end
int cardnum;
int getout = 0;
long ID = 0;

for (cardnum = 0; cardnum &lt; 6; cardnum++) { // can't have more than 6 cards!
workcards[cardnum + 1] = (int)((IDin &gt;&gt;&gt; (8 * cardnum)) &amp; 0xff); // leave the 0 hole for new card
}

// my cards are 2c = 1, 2d = 2 ... As = 52
newcard--; // make 0 based!

workcards[0] = (((newcard &gt;&gt;&gt; 2) + 1) &lt;&lt; 4) + (newcard &amp; 3) + 1; // add next card formats card to rrrr00ss


for (numcards = 0; workcards[numcards]!=0; numcards++) {
suitcount[workcards[numcards] &amp; 0xf]++; // need to see if suit is significant
rankcount[(workcards[numcards] &gt;&gt;&gt; 4) &amp; 0xf]++; // and rank to be sure we don't have 4!

if (numcards!=0) {
if (workcards[0] == workcards[numcards]) { // can't have the same card twice
getout = 1; // if so need to get out after counting numcards
}
}
}


if (getout!=0) {
return 0; // duplicated another card (ignore this one)
}


int needsuited = numcards - 2; // for suit to be significant - need to have n-2 of same suit

if (oldnumcards &lt; numcards) {

System.out.println("Changing to " + numcards + " " + numIDs);
oldnumcards = numcards; // break point here if you need it

}

if (numcards &gt; 4) {
for (int rank = 1; rank &lt; 14; rank++) {
if (rankcount[rank] &gt; 4) { // if I have more than 4 of a rank then I shouldn't do this one!!
return 0; // can't have more than 4 of a rank so return an ID that can't be!
}
}
}

// However in the ID process I prefered that
// 2s = 0x21, 3s = 0x31,.... Kc = 0xD4, Ac = 0xE4
// This allows me to sort in Rank then Suit order

// if we don't have at least 2 cards of the same suit for 4, we make this card suit 0.

if (needsuited &gt; 1) {
for (cardnum = 0; cardnum &lt; numcards; cardnum++) { // for each card
if (suitcount[workcards[cardnum] &amp; 0xf] &lt; needsuited) { // check suitcount to the number I need to have suits significant
workcards[cardnum] &amp;= 0xf0; // if not enough - 0 out the suit - now this suit would be a 0 vs 1-4
}
}
}

// Sort Using XOR. Network for N=7, using Bose-Nelson Algorithm: Thanks to the thread!


SWAP(0, 4);
SWAP(1, 5);
SWAP(2, 6);
SWAP(0, 2);
SWAP(1, 3);
SWAP(4, 6);
SWAP(2, 4);
SWAP(3, 5);
SWAP(0, 1);
SWAP(2, 3);
SWAP(4, 5);
SWAP(1, 4);
SWAP(3, 6);
SWAP(1, 2);
SWAP(3, 4);
SWAP(5, 6);


// long winded way to put the pieces into a long
// cards in bytes --66554433221100
// the resulting ID is a 64 bit value with each card represented by 8 bits.
ID = (long) workcards[0] +
((long) workcards[1] &lt;&lt; 8) +
((long) workcards[2] &lt;&lt; 16) +
((long) workcards[3] &lt;&lt; 24) +
((long) workcards[4] &lt;&lt; 32) +
((long) workcards[5] &lt;&lt; 40) +
((long) workcards[6] &lt;&lt; 48);

return ID;
}

public static void SWAP(int I, int J) {
if (workcards[I] &lt; workcards[J]) {
workcards[I]^=workcards[J];
workcards[J]^=workcards[I];
workcards[I]^=workcards[J];
}
}

public static int DoEval(long IDin) {


// I guess I have some explaining to do here... I used the Cactus Kevs Eval ref http://www.suffecool.net/poker/evaluator.html
// I Love the pokersource for speed, but I needed to do some tweaking to get it my way
// and Cactus Kevs stuff was easy to tweak ;-)
int handrank=9999;
int cardnum;
int workcard;
int rank;
int suit=0;
int mainsuit = 20; // just something that will never hit... need to eliminate the main suit from the iterator
int suititerator = 0;
int holdrank=9999;
workcards=new int[8]; // intentially keeping one as a 0 end
int holdcards[]=new int[8];
int numevalcards = 0;

// See Cactus Kevs page for explainations for this type of stuff...
final int primes[] = { 2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41 };


if (IDin!=0) { // if I have a good ID then do it...
for (cardnum = 0; cardnum &lt; 7; cardnum++) { // convert all 7 cards (0s are ok)
holdcards[cardnum] = (int) ((IDin &gt;&gt;&gt; (8 * cardnum)) &amp; 0xff);
if (holdcards[cardnum] == 0) break; // once I hit a 0 I know I am done
numevalcards++; // if not 0 then count the card

if ((suit = holdcards[cardnum] &amp; 0xf) != 0) { // find out what suit (if any) was significant
mainsuit = suit; // and remember it
}
}


for (cardnum = 0; cardnum &lt; numevalcards; cardnum++) { // just have numcards...
workcard = holdcards[cardnum];

// convert to cactus kevs way!! ref http://www.suffecool.net/poker/evaluator.html
// +--------+--------+--------+--------+
// |xxxbbbbb|bbbbbbbb|cdhsrrrr|xxpppppp|
// +--------+--------+--------+--------+
// p = prime number of rank (deuce=2,trey=3,four=5,five=7,...,ace=41)
// r = rank of card (deuce=0,trey=1,four=2,five=3,...,ace=12)
// cdhs = suit of card
// b = bit turned on depending on rank of card

rank = (workcard &gt;&gt;&gt; 4) - 1; // my rank is top 4 bits 1-13 so convert

suit = workcard &amp; 0xf; // my suit is bottom 4 bits 1-4, order is different, but who cares?
if (suit == 0) { // if suit wasn't significant though...
suit = suititerator++; // Cactus Kev needs a suit!
if (suititerator == 5) // loop through available suits
suititerator = 1;
if (suit == mainsuit) { // if it was the sigificant suit... Don't want extras!!
suit = suititerator++; // skip it
if (suititerator == 5) // roll 1-4
suititerator = 1;
}
}
// now make Cactus Keys Card
workcards[cardnum] = primes[rank] | (rank &lt;&lt; 8) | (1 &lt;&lt; (suit + 11)) | (1 &lt;&lt; (16 + rank));
}

switch (numevalcards) { // run Cactus Keys routines
case 5 : holdrank = eval_5cards(workcards[0],workcards[1],workcards[2],workcards[3],workcards[4]);

break;
// if 6 cards I would like to find HandRank for them
// Cactus Key is 1 = highest - 7362 lowest I need to get the min for the permutations
case 6 :

holdrank = eval_5cards(workcards[0],workcards[1],workcards[2],workcards[3],workcards[4]);
holdrank = min(holdrank, eval_5cards(workcards[0],workcards[1],workcards[2],workcards[3],workcards[5]));
holdrank = min(holdrank, eval_5cards(workcards[0],workcards[1],workcards[2],workcards[4],workcards[5]));
holdrank = min(holdrank, eval_5cards(workcards[0],workcards[1],workcards[3],workcards[4],workcards[5]));
holdrank = min(holdrank, eval_5cards(workcards[0],workcards[2],workcards[3],workcards[4],workcards[5]));
holdrank = min(holdrank, eval_5cards(workcards[1],workcards[2],workcards[3],workcards[4],workcards[5]));

break;
case 7 :

holdrank = eval_7cards(workcards[0],workcards[1],workcards[2],workcards[3],workcards[4],workcards[5],workcards[6]);

break;
default : // problem!! shouldn't hit this...
System.out.println(" Problem with numcards = " + numcards);
break;

}

// I would like to change the format of Catus Kev's ret value to:
// hhhhrrrrrrrrrrrr hhhh = 1 high card -&gt; 9 straight flush
// r..r = rank within the above 1 to max of 2861

handrank = 7463 - holdrank; // now the worst hand = 1

if (handrank &lt; 1278) handrank = handrank - 0 + 4096 * 1; // 1277 high card
else if (handrank &lt; 4138) handrank = handrank - 1277 + 4096 * 2; // 2860 one pair
else if (handrank &lt; 4996) handrank = handrank - 4137 + 4096 * 3; // 858 two pair
else if (handrank &lt; 5854) handrank = handrank - 4995 + 4096 * 4; // 858 three-kind
else if (handrank &lt; 5864) handrank = handrank - 5853 + 4096 * 5; // 10 straights
else if (handrank &lt; 7141) handrank = handrank - 5863 + 4096 * 6; // 1277 flushes
else if (handrank &lt; 7297) handrank = handrank - 7140 + 4096 * 7; // 156 full house
else if (handrank &lt; 7453) handrank = handrank - 7296 + 4096 * 8; // 156 four-kind
else handrank = handrank - 7452 + 4096 * 9; // 10 straight-flushes

}
return handrank; // now a handrank that I like
}
public static int min(int a, int b) {
if (a&lt;b)
return a;
else
return b;
}
public static void doSetup() {
int count = 0;
int card;

long ID;
int IDslot;

int handTypeSum[]=new int[10];

// step through the ID array - always shifting the current ID and adding 52 cards to the end of the array.
// when I am at 7 cards put the Hand Rank in!!
// stepping through the ID array is perfect!!

int IDnum;
int holdid;

System.out.println("\nGetting Card IDs!\n");
// as this loops through and find new combinations it adds them to the end
// I need this list to be stable when I set the handranks (next set) (I do the insertion sort on new IDs these)
// so I had to get the IDs first and then set the handranks

for (IDnum = 0; IDs[IDnum]!=0 || IDnum == 0; IDnum++) { // start at 1 so I have a zero catching entry (just in case)

for (card = 1; card &lt; 53; card++) { // the ids above contain cards upto the current card. Now add a new card
ID = MakeID(IDs[IDnum], card); // get the new ID for it

if (numcards &lt; 7) holdid = SaveID(ID); // and save it in the list if I am not on the 7th card

}

System.out.println("\rID - " + IDnum); // just to show the progress -- this will count up to 612976

}

System.out.println("\nSetting HandRanks!\n");

// this is as above, but will not be adding anything to the ID list, so it is stable

for (IDnum = 0; IDs[IDnum]!=0 || IDnum == 0; IDnum++) { // start at 1 so I have a zero catching entry (just in case)

for (card = 1; card &lt; 53; card++) {
ID = MakeID(IDs[IDnum], card);

if (numcards &lt; 7) IDslot = SaveID(ID) * 53 + 53; // when in the index mode (&lt; 7 cards) get the id to save
else IDslot = DoEval(ID); // if I am at the 7th card, get the HandRank to save

maxHR = IDnum * 53 + card + 53; // find where to put it
HR[maxHR] = IDslot; // and save the pointer to the next card or the handrank
}

if (numcards == 6 || numcards == 7) {
// an extra, If you want to know what the handrank when there is 5 or 6 cards
// you can just do HR[u3] or HR[u4] from below code for Handrank of the 5 or 6 card hand

HR[IDnum * 53 + 53] = DoEval(IDs[IDnum]); // this puts the above handrank into the array
}
//if (IDnum%10000==0)
System.out.println("\rID - " + IDnum); // just to show the progress -- this will count up to 612976 same as above!
}

System.out.println("\nNumber IDs = \nmaxHR = " + numIDs + " " + maxHR); // for warm fuzzys


int c0, c1, c2, c3, c4, c5, c6;
int u0, u1, u2, u3, u4, u5;


//Begin timer, to be done

System.out.println("Starting Test");
for (c0 = 1; c0 &lt; 53; c0++) {
u0 = HR[53+c0];
for (c1 = c0+1; c1 &lt; 53; c1++) {
u1 = HR[u0+c1];
for (c2 = c1+1; c2 &lt; 53; c2++) {
u2 = HR[u1+c2];
for (c3 = c2+1; c3 &lt; 53; c3++) {
u3 = HR[u2+c3];
for (c4 = c3+1; c4 &lt; 53; c4++) {
u4 = HR[u3+c4];
for (c5 = c4+1; c5 &lt; 53; c5++) {
u5 = HR[u4+c5];
for (c6 = c5+1; c6 &lt; 53; c6++) {
handTypeSum[HR[u5+c6] &gt;&gt;&gt; 12]++;
count++;
}
}
}
}
}
}
}

//stop timer, to be done

for (int i = 0; i &lt;= 9; i++) // display the results
System.out.println(handTypeSum[i]);

System.out.println("\nTotal Hands = " + count);

//file output, to be done
}
</pre><hr />
Reply With Quote
  #4  
Old 01-14-2007, 12:58 AM
Mogobu The Fool Mogobu The Fool is offline
Senior Member
 
Join Date: Sep 2005
Location: On teh internets.
Posts: 617
Default Re: 7 Card Hand Evaluators

I'm still loving this thread when I get time to peek at it...

Just as an FYI, you should all feel free to post code, descriptions, etc. over that the overcards.com wiki pages: http://overcards.com/wiki/moin.cgi . The web pages and forums are somewhat dead, what with my retirement from poker, but the wiki pages have a life of their own as a centrum for AHK scripting nuts who play online poker. Feel free to bend the wiki to your own needs to post segments of code to discuss here - the wiki pages will keep an automatic version history of the code changes posted; just peek at the AHK pages for page layout ideas.
Reply With Quote
  #5  
Old 01-14-2007, 11:39 AM
Brad Quick Brad Quick is offline
Junior Member
 
Join Date: Jan 2007
Posts: 1
Default Re: 7 Card Hand Evaluators

This thread got me to register for these forums.

This evaluator is great. I got it running in C++ and with it, I'm able to exaustively calculate the chance of every starting hand winning after the flop in .035 seconds. After the flop is the worst case because there are the most combinations. It goes faster for other game stages.

BTW, this is on an Intel MacBook Pro. [img]/images/graemlins/smile.gif[/img]

- Brad
Reply With Quote
  #6  
Old 01-14-2007, 04:07 PM
RayW RayW is offline
Junior Member
 
Join Date: Mar 2005
Posts: 24
Default Re: 7 Card Hand Evaluators

Hi!

I have run this code in Java (other than the eval routines which I stubbed out with a return 1). They worked great! I also put in within DoEval (after rank = (workcard &gt;&gt;&gt; 4) - 1:
<font class="small">Code:</font><hr /><pre> // my rank is top 4 bits 1-13 so convert
if (rank &gt; 12) {
System.out.println(" Problem with rank = " + rank);
}
</pre><hr />
Which never was hit... I had to put in the heap memory allocator in:
java -Xms130m -Xmx150m HandRankSetup
to keep away from Heap errors. You did well doing the conversion... I believe that your code would work as is!

(Pretty speedy too even in Java!)

Ray...
Reply With Quote
  #7  
Old 01-14-2007, 04:14 PM
mark007 mark007 is offline
Junior Member
 
Join Date: Jan 2007
Posts: 12
Default Re: 7 Card Hand Evaluators

Hi Ray,

Yes the java code "works" up until the point where the actual evaluations are done but breaks there. I do not think it is working correctly therefore as I know my old eval functions work given proper input. Any chance you could help us java folk by adding some printf 's in your c code to show, for example, the actual value of each id as it is created, as they seem to be created differently using my c code..
Reply With Quote
  #8  
Old 01-14-2007, 04:17 PM
RayW RayW is offline
Junior Member
 
Join Date: Mar 2005
Posts: 24
Default Re: 7 Card Hand Evaluators

Hi Mark,

Another thought...

If you aren't using Cactus Kev's routine to do the evaluation of the hand, you would have a problem with the translation of the cards in the DoEval routine!! Are you using Cactus Kev's Eval routines?

Ray...
Reply With Quote
  #9  
Old 01-14-2007, 04:25 PM
mark007 mark007 is offline
Junior Member
 
Join Date: Jan 2007
Posts: 12
Default Re: 7 Card Hand Evaluators

Yep I am, I assume the problem would lie with the creation of the ID's, thanks alot by the way. I can't wait to see how fast this works in java compared to c. If you have a spare minute you might spend a moment to get your c code to print out the value or maybe even binary representation of the Id's as they are created.

Of course to be removed later when the differences are found.
Reply With Quote
  #10  
Old 01-14-2007, 04:32 PM
RayW RayW is offline
Junior Member
 
Join Date: Mar 2005
Posts: 24
Default Re: 7 Card Hand Evaluators

Hi Mark,

I am running your code in Java. It worked fine.... No rank problems as I mentioned (put the rank &gt; 12 code in as above and see if you hit that line). I didn't hit it. Also you need the heap memory increase (I am sure you had that!!). I didn't see anything wrong, and it came through cleanly (including rank). Let me know how you do...

Ray...
Reply With Quote
Reply

Thread Tools
Display Modes

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off

Forum Jump


All times are GMT -4. The time now is 01:59 PM.


Powered by vBulletin® Version 3.8.11
Copyright ©2000 - 2026, vBulletin Solutions Inc.