Texas Hold'em Winner Algorithm

Good, that's why I'm doing AI Texas Hold'em for my older project. I created the gui and betting / deal procedures, but I have reached the part where I need to determine who won the hand, and I don’t know how best to approach this. I am using python btw. The ATM has 2 lists, one for cards of 7 players, one for 7 computer cards. Currently, all cards are stored as a structure in the list as {'Number': XX, 'Suit': x}, where the number is 2-14, the suit is 1-4. The way I was about to approach this is a function for each type of hand, starting from the highest. For example. self.CheckRoyal (playerCards), and manually scroll through the list and see if a royal flush has been reached. There must be a better, numerical way to do this.

+6
python artificial-intelligence poker
source share
5 answers

http://www.codingthewheel.com/archives/poker-hand-evaluator-roundup

The best algorithm you get is 7 looks in a 100 MB search table (if I remember correctly)

+7
source share

The method used in the ralu column is by far the best alternative I've seen. I used this method in my own project and very quickly.

Cliffs:

Do some preprocessing to create a table containing one value for each individual poker hand. Make sure the table is sorted manually.

Each map value has a corresponding initial value. The table is indexed by multiplying each card value in the hand. So, to find the value of the AAAAK hand, you calculate simple multiplication and use this as an index for the table:

int prime = getPrime(hand); // Calculates A.getPrime()...*K.getPrime(); int value = table[prime]; 

(Sorry for the java syntax).

So AAAAK is the same hand as KAAAA, and you don't need a 5-dim table.

Please note that you need to go through all the combinations of the best combination of 5 cards with 7 cards, which you can choose to find the highest value, which is the real value of the hand.

For flushes, another table is used.

The table is becoming quite promising since there are many lost cells in this implementation. To counter this, you can create a map during preprocessing that maps large primary values ​​to integer values ​​and uses this instead of the source.

+2
source share

An example of a ready-made evaluator of the 7 and 5-card Texas Hold'em test can be found here and further explained here . This can help you with productivity. All reviews are welcome at the email address found in it.

+1
source share
 import itertools from collections import Counter # gets the most common element from a list def Most_Common(lst): data = Counter(lst) return data.most_common(1)[0] # gets card value from a hand. converts A to 14, is_seq function will convert the 14 to a 1 when necessary to evaluate A 2 3 4 5 straights def convert_tonums(h, nums = {'T':10, 'J':11, 'Q':12, 'K':13, "A": 14}): for x in xrange(len(h)): if (h[x][0]) in nums.keys(): h[x] = str(nums[h[x][0]]) + h[x][1] return h # is royal flush # if a hand is a straight and a flush and the lowest value is a 10 then it is a royal flush def is_royal(h): nh = convert_tonums(h) if is_seq(h): if is_flush(h): nn = [int(x[:-1]) for x in nh] if min(nn) == 10: return True else: return False # converts hand to number valeus and then evaluates if they are sequential AKA a straight def is_seq(h): ace = False r = h[:] h = [x[:-1] for x in convert_tonums(h)] h = [int(x) for x in h] h = list(sorted(h)) ref = True for x in xrange(0,len(h)-1): if not h[x]+1 == h[x+1]: ref = False break if ref: return True, r aces = [i for i in h if str(i) == "14"] if len(aces) == 1: for x in xrange(len(h)): if str(h[x]) == "14": h[x] = 1 h = list(sorted(h)) for x in xrange(0,len(h)-1): if not h[x]+1 == h[x+1]: return False return True, r # call set() on the suite values of the hand and if it is 1 then they are all the same suit def is_flush(h): suits = [x[-1] for x in h] if len(set(suits)) == 1: return True, h else: return False # if the most common element occurs 4 times then it is a four of a kind def is_fourofakind(h): h = [a[:-1] for a in h] i = Most_Common(h) if i[1] == 4: return True, i[0] else: return False # if the most common element occurs 3 times then it is a three of a kind def is_threeofakind(h): h = [a[:-1] for a in h] i = Most_Common(h) if i[1] == 3: return True, i[0] else: return False # if the first 2 most common elements have counts of 3 and 2, then it is a full house def is_fullhouse(h): h = [a[:-1] for a in h] data = Counter(h) a, b = data.most_common(1)[0], data.most_common(2)[-1] if str(a[1]) == '3' and str(b[1]) == '2': return True, (a, b) return False # if the first 2 most common elements have counts of 2 and 2 then it is a two pair def is_twopair(h): h = [a[:-1] for a in h] data = Counter(h) a, b = data.most_common(1)[0], data.most_common(2)[-1] if str(a[1]) == '2' and str(b[1]) == '2': return True, (a[0], b[0]) return False #if the first most common element is 2 then it is a pair # DISCLAIMER: this will return true if the hand is a two pair, but this should not be a conflict because is_twopair is always evaluated and returned first def is_pair(h): h = [a[:-1] for a in h] data = Counter(h) a = data.most_common(1)[0] if str(a[1]) == '2': return True, (a[0]) else: return False #get the high card def get_high(h): return list(sorted([int(x[:-1]) for x in convert_tonums(h)], reverse =True))[0] # FOR HIGH CARD or ties, this function compares two hands by ordering the hands from highest to lowest and comparing each card and returning when one is higher then the other def compare(xs, ys): xs, ys = list(sorted(xs, reverse =True)), list(sorted(ys, reverse = True)) for i, c in enumerate(xs): if ys[i] > c: return 'RIGHT' elif ys[i] < c: return 'LEFT' return "TIE" # categorized a hand based on previous functions def evaluate_hand(h): if is_royal(h): return "ROYAL FLUSH", h, 10 elif is_seq(h) and is_flush(h) : return "STRAIGHT FLUSH", h, 9 elif is_fourofakind(h): _, fourofakind = is_fourofakind(h) return "FOUR OF A KIND", fourofakind, 8 elif is_fullhouse(h): return "FULL HOUSE", h, 7 elif is_flush(h): _, flush = is_flush(h) return "FLUSH", h, 6 elif is_seq(h): _, seq = is_seq(h) return "STRAIGHT", h, 5 elif is_threeofakind(h): _, threeofakind = is_threeofakind(h) return "THREE OF A KIND", threeofakind, 4 elif is_twopair(h): _, two_pair = is_twopair(h) return "TWO PAIR", two_pair, 3 elif is_pair(h): _, pair = is_pair(h) return "PAIR", pair, 2 else: return "HIGH CARD", h, 1 #this monster function evaluates two hands and also deals with ties and edge cases # this probably should be broken up into separate functions but aint no body got time for that def compare_hands(h1,h2): one, two = evaluate_hand(h1), evaluate_hand(h2) if one[0] == two[0]: if one[0] =="STRAIGHT FLUSH": sett1, sett2 = convert_tonums(h1), convert_tonums(h2) sett1, sett2 = [int(x[:-1]) for x in sett1], [int(x[:-1]) for x in sett2] com = compare(sett1, sett2) if com == "TIE": return "none", one[1], two[1] elif com == "RIGHT": return "right", two[0], two[1] else: return "left", one[0], one[1] elif one[0] == "TWO PAIR": leftover1, leftover2 = is_twopair(h1), is_twopair(h2) twm1, twm2 = max([int(x) for x in list(leftover1[1])]), max([int(x) for x in list(leftover2[1])]) if twm1 > twm2: return "left", one[0], one[1] elif twm1 < twm2: return "right", two[0], two[1] if compare(list(leftover1[1]), list(leftover2[1])) == "TIE": l1 = [x[:-1] for x in h1 if x[:-1] not in leftover1[1]] l2 = [x[:-1] for x in h2 if x[:-1] not in leftover2[1]] if int(l1[0]) == int(l2[0]): return "none", one[1], two[1] elif int(l1[0]) > int(l2[0]): return "left", one[0], one[1] else: return "right", two[0], two[1] elif compare(list(leftover1[1]), list(leftover2[1])) == "RIGHT": return "right", two[0], two[1] elif compare(list(leftover1[1]), list(leftover2[1])) == "LEFT": return "left", one[0], one[1] elif one[0] == "PAIR": sh1, sh2 = int(is_pair(h1)[1]), int(is_pair(h2)[1]) if sh1 == sh2: c1 = [int(x[:-1]) for x in convert_tonums(h1) if not int(sh1) == int(x[:-1])] c2 = [int(x[:-1]) for x in convert_tonums(h2) if not int(sh1) == int(x[:-1])] if compare(c1, c2) == "TIE": return "none", one[1], two[1] elif compare(c1, c2) == "RIGHT": return "right", two[0], two[1] else: return "left", one[0], one[1] elif h1 > h2: return "right", two[0], two[1] else: return "left", one[0], one[1] elif one[0] == 'FULL HOUSE': fh1, fh2 = int(is_fullhouse(h1)[1][0][0]), int(is_fullhouse(h2)[1][0][0]) if fh1 > fh2: return "left", one[0], one[1] else: return "right", two[0], two[1] elif one[0] == "HIGH CARD": sett1, sett2 = convert_tonums(h1), convert_tonums(h2) sett1, sett2 = [int(x[:-1]) for x in sett1], [int(x[:-1]) for x in sett2] com = compare(sett1, sett2) if com == "TIE": return "none", one[1], two[1] elif com == "RIGHT": return "right", two[0], two[1] else: return "left", one[0], one[1] elif len(one[1]) < 5: if max(one[1]) == max(two[1]): return "none", one[1], two[1] elif max(one[1]) > max(two[1]): return "left", one[0], one[1] else: return "right", two[0], two[1] else: n_one, n_two = convert_tonums(one[1]), convert_tonums(two[1]) n_one, n_two = [int(x[:-1]) for x in n_one], [int(x[:-1]) for x in n_two] if max(n_one) == max(n_two): return "none", one[1], two[1] elif max(n_one) > max(n_two): return "left", one[0], one[1] else: return "right", two[0], two[1] elif one[2] > two[2]: return "left", one[0], one[1] else: return "right", two[0], two[1] ''' a = ['QD', 'KD', '9D', 'JD', 'TD'] b = ['JS', '8S', 'KS', 'AS', 'QS'] print compare_hands(a,b) ''' 
+1
source share

Monte Carlo ? This is the first sentence that I see here . This is another senior project. Simple and slow, but otherwise you are probably looking at complex combinatorics, which I will not pretend to know, that I know a lot.

0
source share

All Articles