Began versioning.
[poker.git] / GAMEPLAY.py
1 from DECK import *
2 GLOBAL_TXT = []
3
4 # ***************************************
5 from os import system, kill
6 from popen2 import popen2,popen3
7 class player:
8     def __init__(self, name='', brain=''):
9         self.cash  = 0
10         self.owe   = 0
11         self.option= True
12         self.hole  = []
13         self.IN, self.OUT = 0,0
14         self.brain = brain.strip()
15         self.name  = name+' '
16         self.FOLD  = False
17         self.score = 0
18         self.GP_BUFFER = []
19         
20         if self.brain:
21             self.OUT, self.IN = popen2("./"+self.brain)
22
23     def die(self): 
24         self.IN.write("END\n"); self.IN.flush()
25         system("pkill -9 "+self.name)
26
27     def bet(self, wager, other_player):
28         wager = int(wager)
29         if wager > self.cash: wager  = self.cash
30         if wager < 0:         wager  = 0
31         if wager-self.owe > other_player.cash: 
32             wager = other_player.cash
33         self.cash -= wager
34         self.owe  -= wager
35         self.owe   = self.owe if self.owe < 0 else 0
36         GP("ACTION Player ", self.name, " bets: ", wager)
37         return wager
38     
39     def record_info(self, pot, min_raise, flop, turn, river, other_player):
40         global GLOBAL_TXT
41         self.IN.write("INFO NAME " + str(self.name) + '\n'); self.IN.flush()
42         self.IN.write("INFO ONAME " + str(other_player.name) + '\n'); self.IN.flush()
43         self.IN.write("INFO STACK " + str(self.cash) + '\n'); self.IN.flush()
44         self.IN.write("INFO OSTACK " + str(other_player.cash) + '\n'); self.IN.flush()
45         self.IN.write("INFO POT " + str(pot) + '\n'); self.IN.flush()
46         self.IN.write("INFO MINRAISE " + str(min_raise)+'\n'); self.IN.flush()
47         self.IN.write("INFO OWE " + str(self.owe)  + '\n'); self.IN.flush()
48         self.IN.write("INFO HOLE " + pp_hand(self.hole) + '\n'); self.IN.flush()
49         self.IN.write("INFO FLOP " + pp_hand(flop) + '\n'); self.IN.flush()
50         self.IN.write("INFO TURN " + pp_hand(turn) + '\n'); self.IN.flush()
51         self.IN.write("INFO RIVER " + pp_hand(river) + '\n'); self.IN.flush()
52         self.GP_FLUSH(GLOBAL_TXT)
53
54     def GP_FLUSH(self, TXT):
55         for g in TXT:
56             if g not in self.GP_BUFFER:
57                 self.GP_BUFFER.append(g)
58                 self.IN.write(g + "\n")
59                 self.IN.flush()
60
61     def human_play(self, pot, min_raise, flop, turn, river, other_player):
62         if GLOBAL_TXT: print GLOBAL_TXT[-1]
63         print "[", pp_hand(self.hole), "] Board: ",
64         print "[", pp_hand(flop), pp_hand(turn), pp_hand(river), "]"
65         print "POT: ", pot, " OWE: ", self.owe, " MIN_RAISE: ", min_raise,
66         print "   |   ", "STACK: ", self.cash, "Opp. STACK: ", other_player.cash
67         return raw_input("What do you want to bet, " + self.name + ": ")
68
69     def decide(self, pot, min_raise, flop, turn, river, other_player,endgame=False):
70
71         in_bet = ''
72
73         if not self.brain:
74             in_bet = self.human_play(pot,min_raise, flop, turn, river, other_player)
75
76         else:
77             self.record_info(pot,min_raise,flop,turn,river,other_player)
78             self.IN.write("MOVE \n"); self.IN.flush()
79             in_bet = self.OUT.readline().strip()
80             
81         if endgame: return False
82
83         if in_bet.isalpha(): 
84             in_bet = in_bet.upper()
85             if   in_bet == 'A': in_bet = self.cash
86             elif in_bet == 'C': in_bet = self.owe
87             else              : self.FOLD = True
88         else:
89             try   : in_bet = int(in_bet)
90             except: self.FOLD = True
91
92         if self.FOLD: return False
93
94         if in_bet >= self.cash or in_bet == self.owe or in_bet >= min_raise:
95             out_bet  = self.bet(in_bet, other_player)
96             other_player.owe += out_bet
97             return out_bet
98
99         # Bets between whats owed and min_raise are considered a call
100         if in_bet >= self.owe and in_bet < min_raise:
101             out_bet  = self.bet(self.owe, other_player)
102             other_player.owe += out_bet
103             return out_bet
104
105         # Illegal bets will be counted as folds!
106         GP("ACTION Player ", self.name, "bets ", str(in_bet), " illegally and FOLDS. Valid bets are ", str(self.owe), " or anything >= ", min_raise)
107         self.FOLD = True
108         return False
109
110
111 def GP(*S): GLOBAL_TXT.append(''.join(map(str,S)))
112 def returnGP(): return GLOBAL_TXT
113      
114 def hand_judgement(A,B, board, pot):
115     if    A.FOLD: 
116         GP("ACTION Player ", A.name, " folds" )
117         GP("ACTION Player ", B.name, " wins: ", pot)
118         B.cash += pot
119         return GLOBAL_TXT
120
121     elif  B.FOLD:
122         GP("ACTION Player ", B.name, "folds")
123         GP("ACTION Player ", A.name, "wins: ", pot)
124         A.cash += pot
125         return GLOBAL_TXT
126  
127     S = HOLDEM_score(A, B, board)
128
129     if   S == 1: 
130         GP("ACTION Player ", A.name, "wins: ", pot)
131         A.cash += pot
132         return GLOBAL_TXT
133
134     elif S ==-1: 
135         GP( "ACTION Player ", B.name, "wins: ", pot)
136         B.cash += pot
137         return GLOBAL_TXT
138
139     elif S == 0:
140         GP("ACTION Split pot ")
141         split_pot, carry = pot/2, pot%2
142         A.cash += split_pot + carry
143         B.cash += split_pot
144         return GLOBAL_TXT
145
146 def checkFOLD(A,B):
147     if   A.FOLD or B.FOLD: return True
148     return False
149
150 def betting_round(P,pot,min_raise,flop,turn,river):
151     for player in P: 
152         player.option = True
153
154     while((P[0].owe>0 or P[1].owe>0) or (P[0].option or P[1].option) and (P[0].cash)):
155         action  = P[0].decide(pot, min_raise, flop,turn,river, P[-1])
156         P[0].option = False
157
158         if action >= min_raise: min_raise = 2*action
159         if checkFOLD(P[0],P[1]): return pot
160
161         pot += action
162         P = [P[-1]] + P[:-1] # Cycle the player order
163     return pot
164
165
166 def gameplay(DECK, A, B, smallB, ):
167     global GLOBAL_TXT
168
169     # Shuffle the deck and deal two cards to each player
170     shuffle(DECK)
171
172     A.hole = [DECK[n] for n in xrange(2)  ]
173     B.hole = [DECK[n] for n in xrange(2,4)]
174     board  = [DECK[n] for n in xrange(4,9)]
175
176     flop, turn, river = '', '', ''
177     GLOBAL_TXT        = []
178
179     pot   = 0
180     A.owe = 2*smallB
181     B.owe = smallB
182     A.FOLD, B.FOLD = False, False
183
184     # Handle the case if a player can't post the blinds completely, ALL_IN
185     if    B.owe > B.cash:
186         pot  += B.bet(B.owe, A)
187         pot  += A.bet(pot,   B)
188         return hand_judgement(A,B,board,pot)
189     elif  A.owe > A.cash:
190         pot += A.bet(A.owe,  B)
191         pot += B.bet(pot,    A)
192         return hand_judgement(A,B,board,pot)
193
194     # Both players can post the blinds
195     pot += A.bet(A.owe, B)
196     pot += B.bet(B.owe, A)
197
198     # PRE-FLOP ACTION - Player B is small blind, first to act
199     B.owe        += smallB
200     A.owe        -= smallB
201     min_raise     = smallB*4
202     play_order    = [B,A]
203     pot = betting_round(play_order,pot,min_raise,flop,turn,river)
204     if checkFOLD(A,B): return hand_judgement(A,B,board,pot)
205     if not A.cash or not B.cash: return hand_judgement(A,B,board,pot)
206
207     # FLOP ACTION - Player A is now first to act
208     flop          = board[:3]
209     GP( "ACTION FLOP ", pp_hand(flop) )
210     A.owe, B.owe  = 0, 0
211     min_raise     = smallB*2
212     play_order    = [A,B]
213     pot = betting_round(play_order,pot,min_raise,flop,turn,river)
214     if checkFOLD(A,B): return hand_judgement(A,B,board,pot)
215     if not A.cash or not B.cash: return hand_judgement(A,B,board,pot)
216
217     # TURN ACTION
218     turn          = board[3:4]
219     GP( "ACTION TURN ", pp_hand(turn) )
220     A.owe, B.owe  = 0, 0
221     play_order    = [A,B]
222     pot = betting_round(play_order,pot,min_raise,flop,turn,river)
223     if checkFOLD(A,B): return hand_judgement(A,B,board,pot)
224     if not A.cash or not B.cash: return hand_judgement(A,B,board,pot)
225
226     # RIVER ACTION
227     river         = board[4:5]
228     GP( "ACTION RIVER ", pp_hand(river))
229     A.owe, B.owe  = 0, 0
230     play_order    = [A,B]
231     pot = betting_round(play_order,pot,min_raise,flop,turn,river)
232     if checkFOLD(A,B): return hand_judgement(A,B,board,pot)
233     
234     # SHOWDOWN!
235     return hand_judgement(A,B,board,pot)