--- /dev/null
+from random import randint, choice, seed
+from combinations import *
+
+'''
+Cards in the deck is stored as (n,m), where n is the rank number
+n=[0,12], m=[0,3], with n defined to be the card value and m as the suit.
+
+ Examples:
+ (0,1) is a two of hearts,
+ (11,0) is a king of spades,
+ (12,3) is an Ace of clubs
+'''
+
+DECK = dict().fromkeys(range(52))
+for c in DECK: DECK[c] = (c/4,c%4)
+
+''' Fisher-Yates shuffle from Knuth '''
+def shuffle(DECK):
+ for n in range(1,52)[::-1]:
+ k = randint(0,n-1)
+ DECK[k], DECK[n] = DECK[n], DECK[k]
+
+'''
+To determine which five card hand is stronger according to standard poker
+rules, each hand is given a score and a pair rank. The score cooresponds to
+the poker hand (Straight Flush=8, Four of a Kind=7, etc...). The pair score
+is used to break ties of score. The pair score creates a set of pairs then
+rank sorts within each set. Examples:
+
+Hand A: 7575K
+Hand B: 885A5
+
+Pair Score A: [ (2, [7,5]), (1, [K]) ]
+Pair Score B: [ (2, [8,5]), (1, [A]) ]
+
+Hand A: AKQJ2
+Hand B: 2345A
+
+Pair Score A: [ (1, [A,K,Q,J,2]) ]
+Pair Score B: [ (1, [A,5,4,3,2]) ]
+'''
+
+def pairScore(cards):
+ P = dict().fromkeys(cards,0)
+ for c in cards: P[c] += 1
+ V = sorted(set(P.values()))[::-1]
+ return [[v,sorted([c for c in set(P) if P[c]==v])[::-1]] for v in V]
+
+def top_pairScore(P1,P2): # Only compare to cards with same score!
+ for p1, p2 in zip(P1,P2):
+ if p1[1]>p2[1]: return 1
+ elif p1[1]<p2[1]: return -1
+ return 0
+
+def isFullHouse(P0): return P0==(3,2)
+def isPair4(P0): return P0==(4,1)
+def isPair3(P0): return P0==(3,1)
+def isdoublePair2(P0,P1): return P0==(2,1) and len(P1[0])==2
+def isPair2(P0,P1): return P0==(2,1) and len(P1[0])==1
+def isFlush(suit): return len(set(suit)) == 1
+def isSt(cards) : # Handles the low Ace as well
+ cards = sorted(cards)
+ diff = [(x2-x1) for x1,x2 in zip(cards,cards[1:])]
+ return len([x for x in diff if x==1])==4 or cards==[0,1,2,3,12]
+
+def handScore(H):
+ cards,suit = zip(*H)
+ P = pairScore(cards)
+ P0,P1 = zip(*P)
+
+ score = 0
+ S,F = isSt(cards), isFlush(suit)
+
+ if isPair2(P0,P1) : score = 1
+ elif isdoublePair2(P0,P1): score = 2
+ elif isPair3(P0) : score = 3
+ elif S and not F : score = 4
+ elif F and not S : score = 5
+ elif isFullHouse(P0) : score = 6
+ elif isPair4(P0) : score = 7
+ elif S and F : score = 8
+ return [score, P]
+
+
+'''
+ To determine who wins a poker hand, given two players hole cards, each player
+ determines the best hand they can make within their 7 choose 5 = 21 possible five
+ card combinations. Then each players best hands are put against each other. 1, -1
+ or 0 is returned if player A wins, B wins, or ties respectively.
+'''
+
+# This function prevents call xunqiueCombinations a bajillon times
+HAND_COMBOS = list(xuniqueCombinations(range(7),5))
+def pull_hand(H):
+ for L in HAND_COMBOS: yield [H[n] for n in L]
+
+def top_hand_reduce(P1,P2):
+ H1, A = P1
+ H2, B = P2
+ if A[0]>B[0]: return H1,A
+ elif A[0]<B[0]: return H2,B
+ pairscore = top_pairScore(A[1],B[1])
+ if pairscore > 0: return H1,A
+ elif pairscore < 0: return H2,B
+ return H1,A
+
+def top_hand_score(A,B):
+ A.score,B.score = handScore(A.score), handScore(B.score)
+ if A.score[0]>B.score[0]: return 1
+ elif A.score[0]<B.score[0]: return -1
+ return top_pairScore(A.score[1],B.score[1])
+
+def HOLDEM_score(A, B, board):
+ A.score = reduce(top_hand_reduce,[(H,handScore(H)) for H in pull_hand(A.hole+board)])[0]
+ B.score = reduce(top_hand_reduce,[(H,handScore(H)) for H in pull_hand(B.hole+board)])[0]
+ return top_hand_score(A,B)
+
+# ***************************************
+# Returns the hand in a human readable format (pretty-print)
+def pp_hand(cards):
+ S = ''
+ for c in cards:
+ if c[0]==8: S+='T'
+ elif c[0]==9: S+='J'
+ elif c[0]==10: S+='Q'
+ elif c[0]==11: S+='K'
+ elif c[0]==12: S+='A'
+ else : S+=str(c[0]+2)
+
+ if c[1]==0 : S+='s'
+ elif c[1]==1 : S+='d'
+ elif c[1]==2 : S+='c'
+ else : S+='h'
+ S += ' '
+ return S
+
+def pp_score(A):
+ try:
+ S = ''
+ if A.score[0] == 0: S = 'HighCard '
+ elif A.score[0] == 1: S = 'Pair '
+ elif A.score[0] == 2: S = 'TwoKind '
+ elif A.score[0] == 3: S = 'ThreeKind '
+ elif A.score[0] == 4: S = 'Straight '
+ elif A.score[0] == 5: S = 'Flush '
+ elif A.score[0] == 6: S = 'FullHouse '
+ elif A.score[0] == 7: S = 'FourKind '
+ elif A.score[0] == 8: S = 'StFlush '
+ S += str(A.score[1])
+ return S
+ except:
+ return "INCOMPLETE"
--- /dev/null
+from DECK import *
+GLOBAL_TXT = []
+
+# ***************************************
+from os import system, kill
+from popen2 import popen2,popen3
+class player:
+ def __init__(self, name='', brain=''):
+ self.cash = 0
+ self.owe = 0
+ self.option= True
+ self.hole = []
+ self.IN, self.OUT = 0,0
+ self.brain = brain.strip()
+ self.name = name+' '
+ self.FOLD = False
+ self.score = 0
+ self.GP_BUFFER = []
+
+ if self.brain:
+ self.OUT, self.IN = popen2("./"+self.brain)
+
+ def die(self):
+ self.IN.write("END\n"); self.IN.flush()
+ system("pkill -9 "+self.name)
+
+ def bet(self, wager, other_player):
+ wager = int(wager)
+ if wager > self.cash: wager = self.cash
+ if wager < 0: wager = 0
+ if wager-self.owe > other_player.cash:
+ wager = other_player.cash
+ self.cash -= wager
+ self.owe -= wager
+ self.owe = self.owe if self.owe < 0 else 0
+ GP("ACTION Player ", self.name, " bets: ", wager)
+ return wager
+
+ def record_info(self, pot, min_raise, flop, turn, river, other_player):
+ global GLOBAL_TXT
+ self.IN.write("INFO NAME " + str(self.name) + '\n'); self.IN.flush()
+ self.IN.write("INFO ONAME " + str(other_player.name) + '\n'); self.IN.flush()
+ self.IN.write("INFO STACK " + str(self.cash) + '\n'); self.IN.flush()
+ self.IN.write("INFO OSTACK " + str(other_player.cash) + '\n'); self.IN.flush()
+ self.IN.write("INFO POT " + str(pot) + '\n'); self.IN.flush()
+ self.IN.write("INFO MINRAISE " + str(min_raise)+'\n'); self.IN.flush()
+ self.IN.write("INFO OWE " + str(self.owe) + '\n'); self.IN.flush()
+ self.IN.write("INFO HOLE " + pp_hand(self.hole) + '\n'); self.IN.flush()
+ self.IN.write("INFO FLOP " + pp_hand(flop) + '\n'); self.IN.flush()
+ self.IN.write("INFO TURN " + pp_hand(turn) + '\n'); self.IN.flush()
+ self.IN.write("INFO RIVER " + pp_hand(river) + '\n'); self.IN.flush()
+ self.GP_FLUSH(GLOBAL_TXT)
+
+ def GP_FLUSH(self, TXT):
+ for g in TXT:
+ if g not in self.GP_BUFFER:
+ self.GP_BUFFER.append(g)
+ self.IN.write(g + "\n")
+ self.IN.flush()
+
+ def human_play(self, pot, min_raise, flop, turn, river, other_player):
+ if GLOBAL_TXT: print GLOBAL_TXT[-1]
+ print "[", pp_hand(self.hole), "] Board: ",
+ print "[", pp_hand(flop), pp_hand(turn), pp_hand(river), "]"
+ print "POT: ", pot, " OWE: ", self.owe, " MIN_RAISE: ", min_raise,
+ print " | ", "STACK: ", self.cash, "Opp. STACK: ", other_player.cash
+ return raw_input("What do you want to bet, " + self.name + ": ")
+
+ def decide(self, pot, min_raise, flop, turn, river, other_player,endgame=False):
+
+ in_bet = ''
+
+ if not self.brain:
+ in_bet = self.human_play(pot,min_raise, flop, turn, river, other_player)
+
+ else:
+ self.record_info(pot,min_raise,flop,turn,river,other_player)
+ self.IN.write("MOVE \n"); self.IN.flush()
+ in_bet = self.OUT.readline().strip()
+
+ if endgame: return False
+
+ if in_bet.isalpha():
+ in_bet = in_bet.upper()
+ if in_bet == 'A': in_bet = self.cash
+ elif in_bet == 'C': in_bet = self.owe
+ else : self.FOLD = True
+ else:
+ try : in_bet = int(in_bet)
+ except: self.FOLD = True
+
+ if self.FOLD: return False
+
+ if in_bet >= self.cash or in_bet == self.owe or in_bet >= min_raise:
+ out_bet = self.bet(in_bet, other_player)
+ other_player.owe += out_bet
+ return out_bet
+
+ # Bets between whats owed and min_raise are considered a call
+ if in_bet >= self.owe and in_bet < min_raise:
+ out_bet = self.bet(self.owe, other_player)
+ other_player.owe += out_bet
+ return out_bet
+
+ # Illegal bets will be counted as folds!
+ GP("ACTION Player ", self.name, "bets ", str(in_bet), " illegally and FOLDS. Valid bets are ", str(self.owe), " or anything >= ", min_raise)
+ self.FOLD = True
+ return False
+
+
+def GP(*S): GLOBAL_TXT.append(''.join(map(str,S)))
+def returnGP(): return GLOBAL_TXT
+
+def hand_judgement(A,B, board, pot):
+ if A.FOLD:
+ GP("ACTION Player ", A.name, " folds" )
+ GP("ACTION Player ", B.name, " wins: ", pot)
+ B.cash += pot
+ return GLOBAL_TXT
+
+ elif B.FOLD:
+ GP("ACTION Player ", B.name, "folds")
+ GP("ACTION Player ", A.name, "wins: ", pot)
+ A.cash += pot
+ return GLOBAL_TXT
+
+ S = HOLDEM_score(A, B, board)
+
+ if S == 1:
+ GP("ACTION Player ", A.name, "wins: ", pot)
+ A.cash += pot
+ return GLOBAL_TXT
+
+ elif S ==-1:
+ GP( "ACTION Player ", B.name, "wins: ", pot)
+ B.cash += pot
+ return GLOBAL_TXT
+
+ elif S == 0:
+ GP("ACTION Split pot ")
+ split_pot, carry = pot/2, pot%2
+ A.cash += split_pot + carry
+ B.cash += split_pot
+ return GLOBAL_TXT
+
+def checkFOLD(A,B):
+ if A.FOLD or B.FOLD: return True
+ return False
+
+def betting_round(P,pot,min_raise,flop,turn,river):
+ for player in P:
+ player.option = True
+
+ while((P[0].owe>0 or P[1].owe>0) or (P[0].option or P[1].option) and (P[0].cash)):
+ action = P[0].decide(pot, min_raise, flop,turn,river, P[-1])
+ P[0].option = False
+
+ if action >= min_raise: min_raise = 2*action
+ if checkFOLD(P[0],P[1]): return pot
+
+ pot += action
+ P = [P[-1]] + P[:-1] # Cycle the player order
+ return pot
+
+
+def gameplay(DECK, A, B, smallB, ):
+ global GLOBAL_TXT
+
+ # Shuffle the deck and deal two cards to each player
+ shuffle(DECK)
+
+ A.hole = [DECK[n] for n in xrange(2) ]
+ B.hole = [DECK[n] for n in xrange(2,4)]
+ board = [DECK[n] for n in xrange(4,9)]
+
+ flop, turn, river = '', '', ''
+ GLOBAL_TXT = []
+
+ pot = 0
+ A.owe = 2*smallB
+ B.owe = smallB
+ A.FOLD, B.FOLD = False, False
+
+ # Handle the case if a player can't post the blinds completely, ALL_IN
+ if B.owe > B.cash:
+ pot += B.bet(B.owe, A)
+ pot += A.bet(pot, B)
+ return hand_judgement(A,B,board,pot)
+ elif A.owe > A.cash:
+ pot += A.bet(A.owe, B)
+ pot += B.bet(pot, A)
+ return hand_judgement(A,B,board,pot)
+
+ # Both players can post the blinds
+ pot += A.bet(A.owe, B)
+ pot += B.bet(B.owe, A)
+
+ # PRE-FLOP ACTION - Player B is small blind, first to act
+ B.owe += smallB
+ A.owe -= smallB
+ min_raise = smallB*4
+ play_order = [B,A]
+ pot = betting_round(play_order,pot,min_raise,flop,turn,river)
+ if checkFOLD(A,B): return hand_judgement(A,B,board,pot)
+ if not A.cash or not B.cash: return hand_judgement(A,B,board,pot)
+
+ # FLOP ACTION - Player A is now first to act
+ flop = board[:3]
+ GP( "ACTION FLOP ", pp_hand(flop) )
+ A.owe, B.owe = 0, 0
+ min_raise = smallB*2
+ play_order = [A,B]
+ pot = betting_round(play_order,pot,min_raise,flop,turn,river)
+ if checkFOLD(A,B): return hand_judgement(A,B,board,pot)
+ if not A.cash or not B.cash: return hand_judgement(A,B,board,pot)
+
+ # TURN ACTION
+ turn = board[3:4]
+ GP( "ACTION TURN ", pp_hand(turn) )
+ A.owe, B.owe = 0, 0
+ play_order = [A,B]
+ pot = betting_round(play_order,pot,min_raise,flop,turn,river)
+ if checkFOLD(A,B): return hand_judgement(A,B,board,pot)
+ if not A.cash or not B.cash: return hand_judgement(A,B,board,pot)
+
+ # RIVER ACTION
+ river = board[4:5]
+ GP( "ACTION RIVER ", pp_hand(river))
+ A.owe, B.owe = 0, 0
+ play_order = [A,B]
+ pot = betting_round(play_order,pot,min_raise,flop,turn,river)
+ if checkFOLD(A,B): return hand_judgement(A,B,board,pot)
+
+ # SHOWDOWN!
+ return hand_judgement(A,B,board,pot)
--- /dev/null
+import popen2
+from DECK import *
+from GAMEPLAY import *
+global GLOBAL_TXT
+#import psyco; psyco.full()
+
+start_stack = 1000
+blinds = [1,2,4,8,16,25,37,50]
+hand_clock = 20
+
+# Command line arguments
+import sys
+
+try : A = player(sys.argv[1],sys.argv[1])
+except: A = player('Meg')
+try : B = player(sys.argv[2], sys.argv[2])
+except: B = player('Jack')
+try : tournament_N = int(sys.argv[3])
+except: tournament_N = 1
+
+P = [A,B]
+for n in xrange(tournament_N):
+ A.cash = start_stack
+ B.cash = start_stack
+
+ hand_count,b = 0, 0
+
+ while A.cash > 0 and B.cash > 0:
+ hand_count += 1
+
+ if hand_count % hand_clock==0:
+ b = b+1 if b < len(blinds)-1 else len(blinds)-1
+
+ GLOBAL_TXT = gameplay(DECK, P[0],P[1], blinds[b])
+
+ # Allow the players to view the end result
+ board = [DECK[n] for n in xrange(4,9)]
+ flop,turn,river = board[:3], board[3:4], board[4:5]
+ if not A.FOLD and not B.FOLD:
+ GP("INFO ",A.name, pp_hand(A.hole), pp_score(A), ' ',A.cash)
+ GP("INFO ",B.name, pp_hand(B.hole), pp_score(B), ' ',B.cash)
+ GP("INFO GAMEOVER ", hand_count)
+ for p in P:
+ if p.brain:
+ p.GP_FLUSH(returnGP())
+ p.GP_BUFFER = []
+
+ # Human player text
+ if not A.brain or not B.brain: # or True:
+ for g in GLOBAL_TXT: print g
+ print "INFO BOARD ", pp_hand([DECK[n] for n in xrange(4,9)])
+
+ P = [P[-1]] + P[:-1] # Cycle the player order
+
+ if A.cash: print A.name, hand_count
+ else : print B.name, hand_count
+
+for p in P:
+ if p.brain: p.die() # Kill the players!
+
+
+
+
--- /dev/null
+from __future__ import generators
+
+def xcombinations(items, n):
+ if n==0: yield []
+ else:
+ for i in xrange(len(items)):
+ for cc in xcombinations(items[:i]+items[i+1:],n-1):
+ yield [items[i]]+cc
+
+def xuniqueCombinations(items, n):
+ if n==0: yield []
+ else:
+ for i in xrange(len(items)):
+ for cc in xuniqueCombinations(items[i+1:],n-1):
+ yield [items[i]]+cc
+
+def xselections(items, n):
+ if n==0: yield []
+ else:
+ for i in xrange(len(items)):
+ for ss in xselections(items, n-1):
+ yield [items[i]]+ss
+
+def xpermutations(items):
+ return xcombinations(items, len(items))
+
--- /dev/null
+#!/usr/bin/python
+import sys
+import os
+
+IN, OUT = sys.stdin, sys.stdout
+
+FOUT = open("test_anyAce.txt",'a')
+allin = False
+
+while True:
+ std_in = IN.readline().strip()
+ if std_in:
+ FOUT.write(std_in+'\n')
+
+ std_in = std_in.split(' ')
+ try :
+ tag = std_in[0]
+ type = std_in[1]
+ data = std_in[2:]
+ except:
+ #FOUT.write(str(std_in))
+ tag = std_in[0]
+
+ #FOUT.write(tag+' '+type+' '+str(data)+' '+'\n')
+ if tag == "END" : FOUT.close(); exit()
+ if tag == "MOVE":
+ # You must return a valid bet here
+ if allin: OUT.write("A\n")
+ else : OUT.write("f\n")
+
+ OUT.flush()
+ allin = False
+
+ elif tag == "INFO" and type == "HOLE":
+ # Handle new information
+ # Save info to a file and go all in on any Ace
+ h1, h2 = data[-1], data[-2]
+ #FOUT.write(h1+h2+'\n')
+
+ if h1[0]=='A' or h2[0]=='A': allin = True
--- /dev/null
+#!/usr/bin/python
+import sys
+import os
+
+IN, OUT = sys.stdin, sys.stdout
+
+FOUT = open("test_anyPair.txt",'w')
+allin = False
+
+while True:
+ std_in = IN.readline().strip()
+ if std_in:
+ std_in = std_in.split(' ')
+ try :
+ tag = std_in[0]
+ type = std_in[1]
+ data = std_in[2:]
+ except:
+ FOUT.write(str(std_in))
+ tag = std_in[0]
+
+ #FOUT.write(tag+' '+type+' '+str(data)+' '+'\n')
+
+ if tag == "MOVE":
+ # You must return a valid bet here
+ if allin: OUT.write("A\n")
+ else : OUT.write("f\n")
+ OUT.flush()
+ allin = False
+
+ elif tag == "INFO" and type == "HOLE":
+ # Handle new information
+ # Save info to a file and go all in on any pair
+ h1, h2 = data[-1], data[-2]
+
+ if h1[0] == h2[0] and h1[0]=="A": allin = True
+
+
+
+
+
+
+
+
+
+