PageRenderTime 616ms CodeModel.GetById 32ms RepoModel.GetById 1ms app.codeStats 0ms

/greenlet/poker.py

https://github.com/jaekwon/jae-python
Python | 249 lines | 202 code | 38 blank | 9 comment | 30 complexity | 1bd9b2734a5ab00800d844da5d466d68 MD5 | raw file
  1. import random
  2. #from py.magic import greenlet
  3. from greenlet import greenlet
  4. import pdb
  5. # set up logging
  6. import logging
  7. logging.basicConfig(format="%(name)-20s:\t%(message)s")
  8. logging.debug("program started.")
  9. def random_move(legal_moves):
  10. return random.choice(legal_moves)
  11. FOLD = "fold"
  12. CALL = "call"
  13. BET = "bet"
  14. class Player(greenlet):
  15. def __init__(self, name):
  16. self.name = name
  17. super(Player, self).__init__(self.run, name)
  18. self.bank = 1000
  19. self.log = logging.getLogger(name)
  20. def bring_to_game(self, game):
  21. self.game = game
  22. def run(self):
  23. while True:
  24. move = random_move(self.legal_moves)
  25. self.log.info("[%s] - %s" % (move, str(self.dealt_card)))
  26. self.game.switch(move)
  27. #while True
  28. class Player1(Player):
  29. def __init__(self, name):
  30. super(type(self), self).__init__(name);
  31. self.last_game = None
  32. def run(self):
  33. while True:
  34. move = random_move(self.legal_moves)
  35. self.log.info("gameid: %d" % self.game.game_index)
  36. self.game.switch(move)
  37. class IllegalMoveException(Exception):
  38. pass
  39. class NewRound(Exception):
  40. pass
  41. class NewStage(Exception):
  42. pass
  43. class SimpleGame(greenlet):
  44. def __init__(self):
  45. super(SimpleGame, self).__init__(self.run, "^^game^^")
  46. self.log = logging.getLogger("simple game")
  47. self.level = 1
  48. self.players = [Player1("^^%s^^" % x) for x in range(2)]
  49. for player in self.players:
  50. player.bring_to_game(self)
  51. self.set_debug()
  52. def set_debug(self):
  53. for player in self.players:
  54. player.log.setLevel(logging.INFO)
  55. self.log.setLevel(logging.WARN)
  56. def deal(self, target_player = None):
  57. if target_player == None:
  58. for player in self.players:
  59. player.dealt_card = []
  60. for i in range(2):
  61. dealt = random.choice(list(self.cards))
  62. self.cards.remove(dealt)
  63. player.dealt_card.append(dealt)
  64. else:
  65. target_player.dealt_card = dealt = random.choice(list(self.cards))
  66. self.cards.remove(dealt)
  67. def run(self):
  68. print "starting new round"
  69. self.playeri = PlayerIterator(self.players, 0)
  70. self.playeri.mark()
  71. self.game_index = 0;
  72. for _ in range(100):
  73. try:
  74. self.moves = []
  75. self.table_money = 0
  76. self.playeri.reset()
  77. self.playeri.next() # move button over
  78. self.playeri.mark() # put button down?
  79. self.cards = set(range(52))
  80. self.game_index = self.game_index + 1
  81. def collect_money(player, blinds):
  82. money = blinds * self.level
  83. self.table_money += money
  84. player.bank -= money
  85. self.log.info("%s put $%d" % (player.name, money))
  86. def reward_pot(player):
  87. player.bank += self.table_money
  88. self.log.warn("%s wins pot $%d" % (player.name, self.table_money))
  89. self.table_money = 0
  90. def legal_moves():
  91. moves = [FOLD, CALL, BET]
  92. if self.bet_level == 0:
  93. moves.remove(FOLD)
  94. if self.bet_level == 4:
  95. moves.remove(BET)
  96. return moves
  97. for i in ['single']: # simple game
  98. self.stage = i
  99. self.playeri.reset()
  100. self.bet_level = 0
  101. self.player_bet_levels = {}
  102. self.last_bettor = None
  103. self.log.warn(" ------ %s of game ------ " % i)
  104. # deal cards
  105. for player in self.players:
  106. self.player_bet_levels[player] = 0
  107. if self.stage != 'preflop':
  108. self.deal(player)
  109. if self.stage == 'preflop':
  110. self.deal()
  111. try:
  112. for player in self.playeri:
  113. self.log.debug("switching to player %s" % str(player.name))
  114. player.legal_moves = legal_moves()
  115. player_move = player.switch()
  116. self.moves.append((player, player_move))
  117. if player_move == FOLD:
  118. self.playeri.remove()
  119. self.log.info("player %s folded" % str(player.name))
  120. # reward pot to last player
  121. if len(self.playeri) == 1:
  122. reward_pot(self.playeri.current())
  123. raise NewRound, "player %s won" % self.playeri.current().name
  124. elif player_move == CALL:
  125. self.log.info("player %s called" % str(player.name))
  126. called_blinds = self.bet_level - self.player_bet_levels[player]
  127. collect_money(player, called_blinds)
  128. self.player_bet_levels[player] = self.bet_level
  129. if [self.player_bet_levels[x] for x in self.playeri.players] == [self.bet_level]*len(self.playeri):
  130. raise NewStage, "all players called, new stage coming"
  131. elif player_move == BET:
  132. self.log.info("player %s bet" % str(player.name))
  133. self.last_bettor = player
  134. self.bet_level += 1
  135. bet_blinds = self.bet_level - self.player_bet_levels[player]
  136. collect_money(player, bet_blinds)
  137. self.player_bet_levels[player] = self.bet_level
  138. else:
  139. raise IllegalMoveException, "unknown move!"
  140. except NewStage, e:
  141. self.log.debug(e.message)
  142. #for i in ['preflop', 'flop', 'turn', 'river']: # three stages
  143. #check cards and reward pot to someone
  144. remaining_players = self.playeri.players
  145. if self.last_bettor:
  146. remaining_players.append(self.last_bettor)
  147. winner = max(remaining_players, key=lambda x: x.dealt_card)
  148. reward_pot(winner)
  149. raise NewRound, "showdown"
  150. except NewRound:
  151. self.log.warn(" ---------- new round! ---------- ");
  152. #while True
  153. for player in self.players:
  154. print "player %s:\t%d" % (player.name, player.bank)
  155. class PlayerIterator(object):
  156. """
  157. a = poker.PlayerIterator(['a', 'b', 'c', 'e'], 0)
  158. a.current() # 'a'
  159. a.get(0) # 'a'
  160. a.get(-1) # 'e'
  161. a.next() # 'a'
  162. a.next() # 'b'
  163. a.get(-1) # 'a'
  164. for i in a:
  165. print i # loops forever
  166. """
  167. def __init__(self, players, offset):
  168. assert 0 <= offset < len(players)
  169. self._all_players = players[:]
  170. self.players = players[:]
  171. self.offset = (offset - 1) % len(players)
  172. def __iter__(self):
  173. return self
  174. def next(self):
  175. self.offset = (self.offset + 1) % len(self.players)
  176. return self.players[self.offset]
  177. def current(self):
  178. return self.players[self.offset]
  179. def get(self, relative_index):
  180. return self.players[(self.offset + relative_index) % len(self.players)]
  181. def mark(self):
  182. self._mark = self.offset
  183. def reset(self):
  184. self.players = self._all_players[:]
  185. self.offset = self._mark
  186. def remove(self):
  187. """ Remove current user temporarily from this iterator.
  188. calling "current" will return the previous user
  189. """
  190. if self.players:
  191. del self.players[self.offset]
  192. if self.players:
  193. self.offset = (self.offset - 1) % len(self.players)
  194. else:
  195. raise EmptyException, "cannot remove from an empty list of players"
  196. def __len__(self):
  197. return len(self.players)
  198. game = SimpleGame()
  199. game.switch()