Image Image Image




Post new topic Reply to topic  [ 11 posts ] 
Author Message
 Post subject: *Official* Omaha Hi/Lo Hand Evaluator Thread
PostPosted: Tue Feb 10, 2009 9:31 pm 
Offline
Senior member
User avatar

Posts: 232
Favourite Bot: Poki
Does anyone know of any C# Omaha hi evaluators? I have previously used Keith Rule's c# evaluator for holdem and it was great


Top
 Profile E-mail  
 
 Post subject: Re: C# Omaha Evaluator?
PostPosted: Wed Feb 11, 2009 7:45 am 
Offline
Senior member
User avatar

Posts: 206
Favourite Bot: i7 860
Was the Keith's version using the lookup table approach? If so, I think simply testing every 2-card combination from the 4-card hand and 3-5-card combination from the board cards, ie. worst-case C(4,2)*C(5,3) = 60 possibilities to test, would yield very good performance. Last time I checked, this is what the poker-eval was also doing.

Cheers.


Top
 Profile E-mail  
 
 Post subject: Re: C# Omaha Evaluator?
PostPosted: Wed Feb 11, 2009 10:56 am 
Offline
Senior member
User avatar

Posts: 232
Favourite Bot: Poki
Singularity wrote:
Was the Keith's version using the lookup table approach? If so, I think simply testing every 2-card combination from the 4-card hand and 3-5-card combination from the board cards, ie. worst-case C(4,2)*C(5,3) = 60 possibilities to test, would yield very good performance. Last time I checked, this is what the poker-eval was also doing.

Cheers.


Thank you, I am using that method now. It works great and it's really fast :)


Top
 Profile E-mail  
 
 Post subject: Re: C# Omaha Evaluator?
PostPosted: Wed Aug 19, 2009 9:25 pm 
Offline
Senior member
User avatar

Posts: 179
Location: Germany
Favourite Bot: N/A
Does anyone else use Keith's version for Omaha Evaluation? Tried the last 4 hours to make a 2-card combination of the 4 cards and the same for the board, but obv I'm very dumb :xx08

Also, how could one integrate LUT for this evaluator?


Top
 Profile E-mail  
 
 Post subject: Re: C# Omaha Evaluator?
PostPosted: Tue Aug 25, 2009 4:35 am 
Offline
Senior member
User avatar

Posts: 206
Favourite Bot: i7 860
Bliss wrote:
Does anyone else use Keith's version for Omaha Evaluation? Tried the last 4 hours to make a 2-card combination of the 4 cards and the same for the board, but obv I'm very dumb :xx08

Also, how could one integrate LUT for this evaluator?


You can use any 5-card LUT evaluator for this purpose. The hand with the highest hand rank out of those 60 combinations is your winning hand.

The monkey way:
Code:
for (b1 = 0; b1 < 4; b1++)
{
  for (b2 = b + 1; b2 < 4; b2++)
  {
     ...
     Hand hand = new Hand(new Card[] { board[b1], board[b2], board[b3], hand_cards[h1], hand_cards[h2] });
     int rank = Eval.HandRank(hand);
     if (rank > highest)
     ...
  }
}


Cheers! :drink


Top
 Profile E-mail  
 
 Post subject: Re: C# Omaha Evaluator?
PostPosted: Tue Aug 25, 2009 12:57 pm 
Offline
PokerAI fellow
User avatar

Posts: 7731
Favourite Bot: V12
Steve Brecher (as far as I recall) had Omaha evaluator, and his software is available both in Java and C#.

I'm no 100% sure, but you can check the stickied 7-card hand evaluator thread.

_________________
indiana


Top
 Profile E-mail  
 
 Post subject: Fast Omaha Low evaluation using LUT
PostPosted: Wed Aug 26, 2009 10:35 am 
Offline
Regular member
User avatar

Posts: 81
Favourite Bot: ICM
I've made a fast and quite small LUT (16384 integers + 65536 shorts) for evaluating Omaha low hands, simple to understand and use in almost any language supporting bitoperations like >> and &. The provided tables and codesample should be compatible with C, C#, C++ and possibly Java, it should also be enough for anyone in the need of a fast low evaluation..


Attachments:
File comment: Low evaluation code and lut
lut_omaha_low.zip [18.13 KB]
Downloaded 112 times
Top
 Profile E-mail  
 
 Post subject: Re: *Official* Omaha Hi/Lo Hand Evaluator Thread
PostPosted: Wed Aug 26, 2009 10:11 pm 
Offline
Regular member
User avatar

Posts: 81
Favourite Bot: ICM
To split four cards into twocards hands (and five/four cards into three) is easy, if you have an ulong (unsigned 64 bit) containing the cards as in my low evaluator (see post above) you first create a lookuptable and a function to use it:
Code:
int[] m_lsb = new int[8192]; // least significant bit

public ulong LeastSignificantBit(ulong value)
{
  if ((value & 8191) != 0)
    return (ulong) l_lsb[(value) & 8191);
  else if ((value >> 13 & 8191) != 0)
    return (ulong) l_lsb[(value >> 13) & 8191) << 13;
  else if ((value >> 26 & 8191) != 0)
    return (ulong) l_lsb[(value >> 26) & 8191) << 26;
  else
    return (ulong) l_lsb[(value >> 39) & 8191) << 39;
}


Initialize the table somewhere (in the constructor):
Code:
for (int a = 0; a < 8192; a++)
{
  m_lsb[a] = 0; // Make sure to clear the first position
  for (int b = 1; b <= 4096; b <<=1)
    if ((a & b) != 0)
    {
      m_lsb[a] = b; // Store the least significant bit
      break;
    }
}


Now build all two and three cards hands:
Code:

ulong[] hands = new ulong[6]; // Six twocard combos from a fourcardhand

ulong c1 = LeastSignificantBit(fourcardhand); // Extract card #1
fourcardhand ^= c1; // Remove card #1 from the fourcardhand using xor
ulong c2 = LeastSignificantBit(fourcardhand); // Extract card #2
fourcardhand ^= c2; // Remove card #2 from the fourcardhand using xor
ulong c3 = LeastSignificantBit(fourcardhand); // Extract card #3
fourcardhand ^= c3; // Remove card #3 from the fourcardhand using xor
ulong c4 = fourcardhand; // Only card #4 left in the fourcardhand

// Build all twocard combos
hands[0] = c1 | c2;
hands[1] = c1 | c3;
hands[2] = c1 | c4;
hands[3] = c2 | c3;
hands[4] = c2 | c4;
hands[5] = c3 | c4;


ulong[] tables = null; // We dont know the number of cards on table yet

if (bitcount(table) == 3) // Flop only
{
// Build all threecard combos
  tables = new ulong[] {table}; // This should work?
}
else if (bitcount(table) == 4)
{
  c1 = LeastSignificantBit(table); // Extract card #1
  table ^= c1;
  c2 = LeastSignificantBit(table); // Extract card #2
  table ^= c2;
  c3 = LeastSignificantBit(table); // Extract card #3
  table ^= c3;
  c4 = table;
// Build all threecard combos
  tables = new ulong[] {c1 | c2 | c3, c1 | c2 | c4, c1 | c3 | c4, c2 | c3 | c4 }; // This should work?
}
else
{
  c1 = LeastSignificantBit(table); // Extract card #1
  table ^= c1;
  c2 = LeastSignificantBit(table); // Extract card #2
  table ^= c2;
  c3 = LeastSignificantBit(table); // Extract card #3
  table ^= c3;
  c4 = LeastSignificantBit(table); // Extract card #4
  table ^= c4;
  ulong c5 = table;
// Build all threecard combos
  tables = new ulong[] { c1 | c2 | c3, c1 | c2 | c4, c1 | c2 | c5, c1 | c3 | c4, c1 | c3 | c5, c1 | c4 | c5, c2 | c3 | c4, c2 | c3 | c5, c2 | c4 | c5, c3 | c4 | c5 }; // This should work?
}

// Evaluate all combos
ulong res = 0;
foreach(ulong h in hands)
  foreach(ulong t in tables)
    if (res < evaluate5cardhand(h | t))
      res = evaluate5cardhand(h | t);
return res;


Simple as that, took me ten minutes to make this post on free hand so it isn't very complicated (and compatible with most languages), the easiest way is to download my eval-library from this forum (it is in a post somewhere) though...
This solution is compatible with Keitth Rules code also...


Top
 Profile E-mail  
 
 Post subject: Re: *Official* Omaha Hi/Lo Hand Evaluator Thread
PostPosted: Thu Aug 27, 2009 12:25 am 
Offline
Senior member
User avatar

Posts: 206
Favourite Bot: i7 860
@Trash,

Appreciated. Have you verified the correctness of your LUT/eval by comparing the results to, say, pokereval's output?


Top
 Profile E-mail  
 
 Post subject: Re: *Official* Omaha Hi/Lo Hand Evaluator Thread
PostPosted: Thu Aug 27, 2009 7:41 am 
Offline
Regular member
User avatar

Posts: 81
Favourite Bot: ICM
* REMOVED DUE TO NEXT POST *


Top
 Profile E-mail  
 
 Post subject: Re: *Official* Omaha Hi/Lo Hand Evaluator Thread
PostPosted: Thu Aug 27, 2009 8:55 am 
Offline
Regular member
User avatar

Posts: 81
Favourite Bot: ICM
@Singularity: No I have not. Here is the code I used to create the tables, hope it can be proven to be useful:
Code:
#region Private declares
private short[] m_lowresults = new short[65536];
private int[] m_lowhandcards = new int[8192];
private int[] m_lowtablecards = new int[8192];
private int[] m_bitcount = new int[8192];
private int[] m_lsb = new int[8192];
#endregion

#region Initialization
/// <summary>
/// Fills all the needed tables
/// </summary>
private InitTables()
{
   // Initiate needed tables
   for (int a = 0; a < 65536; a++)
   {
      // Initiate low result to 256 (equals a not valid low hand)
      m_lowresults[a] = 256;
      // If a is less than 8192 build supplimentary tables
      if (a < 8192)
      {
         // Count the number of bits set to 1 in a
         m_bitcount[a] = 0;
         for (int b = 1; b < m_bitcount.Length; b <<= 1)
            if ((a & b) != 0)
               m_bitcount[a]++;
         // Find the least significant bit for a
         m_lsb[a] = 0;
         for (int b = 1; b < m_lsb.Length; b <<= 1)
            if ((a & b) != 0)
            {
               m_lsb[a] = b;
               break;
            }
         // Translate a (see it as ranks containing up to 13 cards) to a low hand, valid or unvalid does not matter
         int c = a & 8191;
         // Does the low hand contain an ace?
         if ((c & 4096) == 0)
            // No, just keep the seven lowest bits and set the ace bit to 0
            c = (c & 127) << 1;
         else
            // Yes, keep the seven lowest bits and set the ace bit to 1
            c = ((c & 127) << 1) | 1;
         // Setup the low hands
         m_lowhandcards[a] = c;
         // Setup the low tables
         m_lowtablecards[a] = c << 8;
      }
   }
   // Loop all hands containing A->8
   for (int a = 0; a < 256; a++)
      // Loop all cardcombinations on table containing A->8
      for (int b = 0; b < 256; b++)
      {
         // Check for a valid hand (2-4 cards 8 or below on hand)
         if (m_bitcount[a] > 4 || m_bitcount[a] < 2)
            // None found, skip this hand and move to next
            break;
         // Check for a valid table, needs to have 3 to 5 cards between A and 8
         if (m_bitcount[b] <= 5 && m_bitcount[b] >= 3)
         {
            int[] hands = null, tables = null;
            // Check for number of low cards on hand
            if (m_bitcount[a] == 2)
               // Two cards, only one handcombo to evaluate
               hands = new int[] { a };
            else if (m_bitcount[a] == 3)
            {
               // Three cards, three handcombos to evaluate
               int e = a;
               int c_1 = m_lsb[e];
               e ^= m_lsb[e];
               int c_2 = m_lsb[e];
               e ^= m_lsb[e];
               int c_3 = e;
               hands = new int[]{ c_1 | c_2, c_1 | c_3, c_3 | c_2 };
            }
            else if (m_bitcount[a] == 4)
            {
               // Four cards, six handcombos to evaluate
               int e = a;
               int c_1 = m_lsb[e];
               e ^= m_lsb[e];
               int c_2 = m_lsb[e];
               e ^= m_lsb[e];
               int c_3 = m_lsb[e];
               e ^= m_lsb[e];
               int c_4 = e;
               hands = new int[] { c_1 | c_2, c_1 | c_3, c_1 | c_4, c_2 | c_3, c_2 | c_4, c_3 | c_4 };
            }
            // Check for number of low cards on table
            if (m_bitcount[b] == 3)
               // Three cards, only one tablecombo to evaluate
               tables = new int[] { b };
            else if (m_bitcount[b] == 4)
            {
               // Four cards, four tablecombos to evaluate
               int c = b;
               int c1 = m_lsb[c];
               c ^= c1;
               int c2 = m_lsb[c];
               c ^= c2;
               int c3 = m_lsb[c];
               c ^= c3;
               int c4 = c;
               tables = new int[] { c1 | c2 | c3, c1 | c2 | c4, c1 | c3 | c4, c2 | c3 | c4 };
            }
            else if (m_bitcount[b] == 5)
            {
               // Five cards, ten tablecombos to evaluate
               int c = b;
               int c1 = m_lsb[c];
               c ^= c1;
               int c2 = m_lsb[c];
               c ^= c2;
               int c3 = m_lsb[c];
               c ^= c3;
               int c4 = m_lsb[c];
               c ^= c4;
               int c5 = c;
               tables = new int[] { c5 | c4 | c3, c5 | c2 | c3, c1 | c4 | c5, c1 | c3 | c5, c1 | c2 | c3, c1 | c2 | c5, c1 | c2 | c4, c1 | c3 | c4, c2 | c3 | c4 };
            }
            // Evaluate all of the combos, keep the best combo in the lut
            for (int f = 0; f < hands.Length; f++)
               for (int d = 0; d < tables.Length; d++)
                  // Does the table and hand combine in to a legal hand?
                  if (m_bitcount[hands[f] | tables[d]] == 5)
                     // Yes, is it better than the (il)legal last stored?
                     if (m_lowresults[(a | (b << 8))] > (hands[f] | tables[d]))
                        // Yes, store it in the lut
                        m_lowresults[(a | (b << 8))] = (short) (hands[f] | tables[d]);
         }
      }
}
#endregion


Top
 Profile E-mail  
 
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 11 posts ] 


Who is online

Users browsing this forum: Google and 8 guests


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Jump to: