Пример #1
0
class PokerHandEval:
    def __init__(self):
        self.hand_groups = {
            "A": ["AA", "AKs", "KK"],
            "B": ["AK", "QQ"],
            "C": ["JJ", "TT"],
            "D": ["AQs", "AQ", "AJs", "99", "88"],
            "E": ["AJ", "ATs", "KQs", "77", "66", "55"],
            "F": ["AT", "KQ", "KJs", "QJs", "44", "33", "22"],
            "G": [
                "A9s", "A8s", "A7s", "A6s", "A5s", "A4s", "A3s", "A2s", "KTs",
                "QTs", "JTs", "J9s", "T9s", "98s"
            ],
            "H": ["KJ", "KT", "QJ", "J8s", "T8s", "87s", "76s"]
        }
        self.hand_values = {
            "A": 13,
            "K": 12,
            "Q": 11,
            "J": 10,
            "T": 9,
            "9": 8,
            "8": 7,
            "7": 6,
            "6": 5,
            "5": 4,
            "4": 3,
            "3": 2,
            "2": 1
        }
        self.odds_map = {
            "flop": {
                1: 0.045,
                2: 0.088,
                3: 0.13,
                4: 0.172,
                5: 0.212,
                6: 0.252,
                7: 0.29,
                8: 0.327,
                9: 0.364,
                10: 0.399,
                11: 0.433,
                12: 0.467,
                13: 0.499,
                14: 0.53,
                15: 0.561,
                16: 0.59,
                17: 0.618
            },
            "turn": {
                1: 0.023,
                2: 0.045,
                3: 0.68,
                4: 0.091,
                5: 0.114,
                6: 0.136,
                7: 0.159,
                8: 0.182,
                9: 0.205,
                10: 0.227,
                11: 0.25,
                12: 0.273,
                13: 0.295,
                14: 0.318,
                15: 0.341,
                16: 0.364,
                17: 0.386
            }
        }
        self.eval = PokerEval()

    def prepareHand(self, hand):
        h = hand.split(" ")
        if self.hand_values[h[1][0]] > self.hand_values[h[0][0]]:
            self.hand = "%s%s" % (h[1][0], h[0][0])
        else:
            self.hand = "%s%s" % (h[0][0], h[1][0])
        if h[0][1] == h[1][1]:
            self.hand += "s"

    def getHandGroup(self):
        for group in self.hand_groups:
            if self.hand in self.hand_groups[group]:
                return group
        return False

    def getHandValue(self, game, serial):
        hand = game.getHandAsString(serial)
        board = game.getBoardAsString()
        board_list = board.split(" ")
        if len(board_list) < 5:
            for i in range(len(board_list), 5):
                board_list.append("__")
        hand_list = hand.split(" ")
        cards = hand_list + board_list
        return self.eval.best_hand("hi", self.eval.string2card(cards), [])

    def parseHistory(self, hist):
        self.round_action = {}
        self.action2serials = {"call": [], "raise": [], "fold": []}
        self.serial2action = {}
        ret = ""
        for event in hist:
            type = event[0]
            if type in ["fold", "check", "call", "raise"]:
                if len(event) == 3:
                    (action, serial, amount) = event
                else:
                    (action, serial) = event
                    amount = False
                ret = "action: %s, serial:%d" % (action, serial)
                if amount:
                    ret += ", amount = %d" % amount
                    self.round_action[serial] = [action, amount]
                else:
                    self.round_action[serial] = [action]
                self.serial2action[serial] = action
                if action in self.action2serials.keys():
                    if not serial in self.action2serials[action]:
                        self.action2serials[action].append(serial)

    def getPosition(self, game, serial):
        me = game.serial2player[serial]
        players = game.serialsAllSorted()
        for player in players:
            user = game.serial2player[player]
        user_positions = {}
        player_seats = {}
        i = 1
        for p in game.serialsAllSorted():
            user = game.serial2player[p]
            player_seats[user.seat] = p
        max_seat = len(player_seats)
        early = max_seat / 3
        middle = early * 2
        self.my_seat = me.seat
        self.serial2position = {}
        self.position2serials = {"early": [], "middle": [], "late": []}
        for p in player_seats.keys():
            player_serial = player_seats[p]
            if i <= early:
                position = "early"
            elif i >= (early + 1) and i <= middle:
                position = "middle"
            else:
                position = "late"
            if not player_serial in self.serial2position.keys():
                self.serial2position[player_serial] = position
            if not player_serial in self.position2serials[position]:
                self.position2serials[position].append(player_serial)
            if p == self.my_seat:
                self.position = position
            i += 1
Пример #2
0
print "winners omaha = %s\n" % pokereval.winners(
    game="omaha",
    pockets=[["tc", "ac", "ks", "kc"], ["th", "ah", "qs", "qc"], ["8c", "6h", "js", "jc"]],
    dead=[],
    board=["7h", "3s", "2c", "7s", "7d"],
)
print "winners omaha8 = %s\n" % pokereval.winners(
    game="omaha8",
    pockets=[["tc", "ac", "ks", "kc"], ["th", "ah", "qs", "qc"], ["8c", "6h", "js", "jc"]],
    dead=[],
    board=["7h", "3s", "2c", "7s", "7d"],
)

hand = ["Ac", "As", "Td", "7s", "7h", "3s", "2c"]
best_hand = pokereval.best_hand("hi", hand)
print "best hand from %s = %s" % (hand, pokereval.best_hand("hi", hand))
print "best hand from %s = (%s) %s " % (hand, best_hand[0], [pokereval.card2string(i) for i in best_hand[1:]])

print ""
hand = ["Ah", "Ts", "Kh", "Qs", "Js"]
best_hand = pokereval.best_hand("hi", hand)
print "best hand from %s = %s" % (hand, pokereval.best_hand("hi", hand))
print "best hand from %s = (%s) %s " % (hand, best_hand[0], [pokereval.card2string(i) for i in best_hand[1:]])

print ""
hand = ["2h", "Kh", "Qh", "Jh", "Th"]
best_hand = pokereval.best_hand("hi", hand)
print "best hand from %s = %s" % (hand, pokereval.best_hand("hi", hand))
print "best hand from %s = (%s) %s " % (hand, best_hand[0], [pokereval.card2string(i) for i in best_hand[1:]])
Пример #3
0
class PokerHandEval:
    def __init__(self):
        self.hand_groups = {
            "A":["AA", "AKs", "KK"],
            "B":["AK", "QQ"],
            "C":["JJ", "TT"],
            "D":["AQs", "AQ", "AJs", "99", "88"],
            "E":["AJ","ATs","KQs", "77","66","55"],
            "F":["AT","KQ","KJs","QJs","44","33","22"],
            "G":["A9s","A8s","A7s","A6s","A5s","A4s","A3s","A2s","KTs","QTs","JTs","J9s","T9s","98s"],
            "H":["KJ","KT","QJ","J8s","T8s","87s","76s"]
        }
        self.hand_values = {"A":13,"K":12,"Q":11,"J":10, "T":9,"9":8,"8":7,"7":6,"6":5,"5":4,"4":3,"3":2,"2":1}
        self.odds_map = {
            "flop":{1:0.045,2:0.088,3:0.13,4:0.172,5:0.212,6:0.252,7:0.29,8:0.327,9:0.364,10:0.399,11:0.433,12:0.467,13:0.499,14:0.53,15:0.561,16:0.59,17:0.618},
            "turn":{1:0.023,2:0.045,3:0.68,4:0.091,5:0.114,6:0.136,7:0.159,8:0.182,9:0.205,10:0.227,11:0.25,12:0.273,13:0.295,14:0.318,15:0.341,16:0.364,17:0.386}
        }
        self.eval = PokerEval()
    def prepareHand(self, hand):
        h = hand.split(" ")
        if self.hand_values[h[1][0]] > self.hand_values[h[0][0]]:
            self.hand = "%s%s" % (h[1][0],h[0][0])
        else:
            self.hand = "%s%s" % (h[0][0],h[1][0])
        if h[0][1] == h[1][1]:
            self.hand += "s"
    def getHandGroup(self):
        for group in self.hand_groups:
            if self.hand in self.hand_groups[group]:
                return group
        return False
    def getHandValue(self, game, serial):
        hand = game.getHandAsString(serial)
        board = game.getBoardAsString()
        board_list = board.split(" ")
        if len(board_list) < 5:
            for i in range(len(board_list), 5):
                board_list.append("__")
        hand_list = hand.split(" ")
        cards = hand_list + board_list
        return self.eval.best_hand("hi", self.eval.string2card(cards), [] )
    def parseHistory(self, hist):
        self.round_action = {}
        self.action2serials = {
            "call":[],
            "raise":[],
            "fold":[]
        }
        self.serial2action = {}
        ret = ""
        for event in hist:
            type = event[0]
            if type in ["fold","check","call","raise"]:
                if len(event) == 3:
                    (action, serial, amount) = event
                else:
                    (action,serial) = event
                    amount = False
                ret = "action: %s, serial:%d" % (action, serial)
                if amount:
                    ret += ", amount = %d" % amount
                    self.round_action[serial] = [action, amount]
                else:
                    self.round_action[serial] = [action]
                self.serial2action[serial] = action
                if action in self.action2serials.keys():
                    if not serial in self.action2serials[action]:
                        self.action2serials[action].append(serial)
    def getPosition(self, game, serial):
        me = game.serial2player[serial]
        players = game.serialsAllSorted()
        for player in players:
            user = game.serial2player[player]
        user_positions = {}
        player_seats = {}
        i=1
        for p in game.serialsAllSorted():
            user = game.serial2player[p]
            player_seats[user.seat] = p
        max_seat = len(player_seats)
        early = max_seat / 3
        middle = early * 2
        self.my_seat = me.seat
        self.serial2position = {}
        self.position2serials = {
            "early":[],
            "middle":[],
            "late":[]
        }
        for p in player_seats.keys():
            player_serial = player_seats[p]
            if i <= early:
                position = "early"
            elif i >= (early + 1) and i <= middle:
                position = "middle"
            else:
                position = "late"
            if not player_serial in self.serial2position.keys():
                self.serial2position[player_serial] = position
            if not player_serial in self.position2serials[position]:
                self.position2serials[position].append(player_serial)
            if p == self.my_seat:
                self.position = position
            i += 1
Пример #4
0
print "winners omaha = %s\n" % pokereval.winners(
    game="omaha",
    pockets=[["tc", "ac", "ks", "kc"], ["th", "ah", "qs", "qc"],
             ["8c", "6h", "js", "jc"]],
    dead=[],
    board=["7h", "3s", "2c", "7s", "7d"])
print "winners omaha8 = %s\n" % pokereval.winners(
    game="omaha8",
    pockets=[["tc", "ac", "ks", "kc"], ["th", "ah", "qs", "qc"],
             ["8c", "6h", "js", "jc"]],
    dead=[],
    board=["7h", "3s", "2c", "7s", "7d"])

hand = ["Ac", "As", "Td", "7s", "7h", "3s", "2c"]
best_hand = pokereval.best_hand("hi", hand)
print "best hand from %s = %s" % (hand, pokereval.best_hand("hi", hand))
print "best hand from %s = (%s) %s " % (
    hand, best_hand[0], [pokereval.card2string(i) for i in best_hand[1:]])

print ""
hand = ["Ah", "Ts", "Kh", "Qs", "Js"]
best_hand = pokereval.best_hand("hi", hand)
print "best hand from %s = %s" % (hand, pokereval.best_hand("hi", hand))
print "best hand from %s = (%s) %s " % (
    hand, best_hand[0], [pokereval.card2string(i) for i in best_hand[1:]])

print ""
hand = ["2h", "Kh", "Qh", "Jh", "Th"]
best_hand = pokereval.best_hand("hi", hand)
print "best hand from %s = %s" % (hand, pokereval.best_hand("hi", hand))
Пример #5
0
class Table(object):
    def __init__(self, protocol, avatar, table_info):
        self.protocol = protocol
        self.id = table_info.get('id', 0)
        self.seat = table_info.get('player_seated', -1)
        self.seats = [0] * table_info.get('seats', 10)
        if self.seat != -1:
            self.seats[self.seat] = avatar.serial
            assert avatar.seat == self.seat, "as %s, ss %s" % (avatar.seat,
                                                               self.seat)
        self.name = table_info.get('name', 'unnamed')
        self.betting_structure = table_info['betting_structure']
        blinds, buy_ins, limit = table_info['betting_structure'].split('_')
        min_buy_in, max_buy_in = buy_ins.split('-')
        small, big = blinds.split('-')

        self.max_buy_in = int(max_buy_in) * 100
        self.min_buy_in = int(min_buy_in) * 100
        self.big_blind = int(big) * 100
        self.small_blind = int(small) * 100

        self.players = {avatar.serial: avatar}
        self.avatar = avatar
        self._serial_and_game_id = dict(serial=avatar.serial, game_id=self.id)
        self._eval = PokerEval()
        self.reset()
        self._game_state = GAME_STATE_NULL

    def reset(self):
        """reseting game states for a new hand"""
        self.board_cards = []
        self.position = -1
        self._reset_players()

    def getBoardCards(self):
        """return a list of board games"""
        return list(map(lambda x: x & 63, self.board_cards))

    def getAvatarInfo(self):
        """return a string of usefull information about the avatar"""
        return ", ".join(self._get_avatar_info())

    def isInPosition(self, serial):
        """returs true if player with serial is in position"""
        return serial in self.in_game and self.position == self.in_game.index(
            serial)

    def logIt(self, astr, prefix=" [D] "):
        """a little helper function to log output"""
        self.protocol.logIt(astr, prefix=prefix)

    def updateSeats(self, seats):
        """update seat information"""
        for index, (old, new) in enumerate(zip(self.seats, seats)):
            if old == 0 and new != 0:
                self.addPlayer(index, new)
            elif old != 0 and new == 0:
                self.removePlayer(index)
            elif old != new:
                self.removePlayer(index)
                self.addPlayer(index, new)
                self.logIt("warning idx %s, old %s, new %s" %
                           (index, old, new))

    def addPlayer(self, index, serial):
        """Add player to this table"""
        self.seats[index] = serial
        # Request more information about this player
        if serial == self.avatar.serial:
            self.players[index] = self.avatar
        else:
            self.protocol.sendPacket(
                networkpackets.PacketPokerGetUserInfo(serial=serial))

    def removePlayer(self, index):
        """remove player from this table"""
        serial = self.seats[index]
        self.seats[index] = 0
        if serial in self.players:
            del self.players[serial]

    def updatePlayer(self, player_info):
        """update general palyer information (we requested them in addPlayer)"""
        player = self._get_or_create_player(**player_info)
        player.update(player_info)

    def updatePlayerChips(self, serial, chips, bet):
        """update players chips"""
        player = self._get_or_create_player(serial=serial)
        return player.updateChips(chips, bet)

    def updatePlayerCards(self, serial, cards):
        """update players cards"""
        player = self._get_player(serial)
        player.updateCards(cards)

    def rebuy(self, serial, amount):
        """update money state of player because a rebuy happend"""
        player = self._get_player(serial)
        player.rebuy(amount)

    def _reset_players(self):
        """reset player states"""
        for player in self.players.values():
            player.reset()

    def highestBetNotFold(self):
        """returns the highest bet of all players that are not fold"""
        return max([0] + [
            p._bet for p in self.players.values()
            if p.serial in self.in_game and p.notFold()
        ])

    def inSmallBlindPosition(self):
        """returns True if the player in position is in small_blind position"""
        return len(self.in_game) > 0 and ((self.dealer + 1) %
                                          len(self.in_game)) == self.position

    def bigBlind(self):
        """returns the big_blind of the current table"""
        return self.big_blind or 0

    def doBuyIn(self):
        """actually request a buy_in"""
        self.protocol.sendPacket(
            networkpackets.PacketPokerBuyIn(amount=self.max_buy_in,
                                            **self._serial_and_game_id))
        self.protocol.sendPacket(
            networkpackets.PacketPokerAutoBlindAnte(
                **self._serial_and_game_id))

    def doRebuy(self, amount):
        """actually request a rebuy"""
        self.protocol.sendPacket(
            networkpackets.PacketPokerRebuy(amount=amount,
                                            **self._serial_and_game_id))

    def doSit(self):
        """actually request a sit"""
        self.protocol.sendPacket(
            networkpackets.PacketPokerSit(**self._serial_and_game_id))

    def doSitOut(self):
        """actually request a sitout"""
        self.protocol.sendPacket(
            networkpackets.PacketPokerSitOut(**self._serial_and_game_id))

    def doQuit(self):
        """actually request a table quit"""
        self.protocol.sendPacket(
            networkpackets.PacketPokerTableQuit(**self._serial_and_game_id))

    def doFold(self):
        """actually request a fold"""
        self.protocol.sendPacket(
            networkpackets.PacketPokerFold(**self._serial_and_game_id))

    def doCheck(self):
        """actually request a check"""
        self.protocol.sendPacket(
            networkpackets.PacketPokerCheck(**self._serial_and_game_id))

    def doCall(self):
        """actually request a call"""
        self.protocol.sendPacket(
            networkpackets.PacketPokerCall(**self._serial_and_game_id))

    def doAllIn(self):
        """actually raise all chips"""
        self.doRaise(self.avatar.getChips())

    def doRaise(self, amount):
        """
            actually request a raise by a given amount.
            WARNING: If the amount you requested is too low, the raise will be accepted but the 
            minimum amount to raise will be used instead. You will be informend about the amount 
            that is used to raise.
        """
        self.protocol.sendPacket(
            networkpackets.PacketPokerRaise(amount=amount,
                                            **self._serial_and_game_id))

    def explain(self, packet, state):
        """packets that might be interesting for the game will be handled here"""
        def handlePacketPokerBuyInLimits(packet):
            self.max_buy_in = packet.max
            self.min_buy_in = packet.min

        def handlePacketPokerSeats(packet):
            return self.updateSeats(packet.seats)

        def handlePacketPokerPlayerInfo(packet):
            self.updatePlayer(packet.__dict__)

        def handlePacketPokerPlayerChips(packet):
            return self.updatePlayerChips(packet.serial,
                                          chips=packet.money,
                                          bet=packet.bet)

        def handlePacketPokerPlayerArrive(packet):
            self.updatePlayer(packet.__dict__)

        def handlePacketPokerPlayerLeave(packet):
            self.removePlayer(packet.seat)

        def handlePacketPokerSit(packet):
            self._get_player(packet.serial).sit()

        def handlePacketPokerSitOut(packet):
            self._get_player(packet.serial).sitOut()

        def handlePacketPokerRebuy(packet):
            assert self.id == packet.game_id
            self.rebuy(packet.serial, packet.amount)

        def handlePacketPokerInGame(packet):
            assert self.id == packet.game_id
            self.in_game = packet.players

        def handlePacketPokerPosition(packet):
            assert self.id == packet.game_id
            self.position = packet.position

        def handlePacketPokerStart(packet):
            assert self.id == packet.game_id
            self.reset()
            self.hand_serial = packet.hand_serial

        def handlePacketPokerDealer(packet):
            assert self.id == packet.game_id
            # assert self.dealer == packet.previous_dealer
            self.dealer = packet.dealer

        def handlePacketPokerPlayerCards(packet):
            self.updatePlayerCards(packet.serial, packet.cards)
            if packet.serial == self.avatar.serial:
                self.logIt("You got %r" % self._cards_to_string(packet.cards))

        def handlePacketPokerBoardCards(packet):
            self.board_cards = packet.cards

        def handlePacketPokerRaise(packet):
            self._get_player(packet.serial).bet(packet.amount)

        def handlePacketPokerCall(packet):
            player = self._get_player(packet.serial)
            highestbet = self.highestBetNotFold()
            bigb = self.bigBlind(
            ) if self._game_state == GAME_STATE_PRE_FLOP and not self.inSmallBlindPosition(
            ) else 0
            # import rpdb2; rpdb2.start_embedded_debugger("haha")
            self.logIt("%r, %r" % (highestbet, bigb))
            amount = min(max(highestbet, bigb) - player._bet, player.money)
            player.bet(amount)

        def handlePacketPokerState(packet):
            self._game_state = packet.string

        def handlePacketPokerBlind(packet):
            self._get_player(packet.serial).bet(packet.amount)

        try:
            handle = locals()["handle" + packet.__class__.__name__]
            return handle(packet)
        except KeyError:
            # self.logIt(" explain cant handle : %r" % packet.__class__.__name__)
            return True
        except Exception:
            exc_type, exc_value, exc_traceback = sys.exc_info()
            self.logIt(packet.__class__.__name__,
                       prefix=" EEE  handle failed: ")

            for exline in traceback.format_exception(exc_type, exc_value,
                                                     exc_traceback):
                for line in exline.split('\n'):
                    self.logIt(str(line), prefix=" EEE ")

    def _cards_to_string(self, cards):
        """return a string for cards in a human readable way"""
        return repr(self._eval.card2string(map(lambda x: x & 63, cards)))\
            #.lower().replace("h", u"\u2761").replace("s", u"\u2660").replace("c", u"\u2663").replace("d", u"\u2662")

    def _get_or_create_player(self, serial, seat=None, **player_info):
        """returns the player with the serial, the player will be created if it does not exist yet"""
        # serial = player_info['serial']
        # seat = player_info['seat']
        if seat and self.seats[seat] != 0 and serial != self.seats[seat]:
            self.logIt("%s is allready on seat %s, cleared" %
                       (self.seats[seat], seat))
            del self.players[self.seats[seat]]
            self.seats[seat] = serial

        if serial not in self.players:
            self.players[serial] = Player(serial=serial,
                                          seat=seat,
                                          **player_info)

        return self.players[serial]

    def _get_player(self, serial):
        """returns the player, raises an IndexError if it does not exist"""
        return self.players[serial]

    def _log_players(self):
        """ log player informations """
        self.logIt("Players:")
        for player in self.players.itervalues():
            self.logIt(player._player_info())
        self.logIt("")

    def getDebugLines(self):
        """returns a list of debug lines (yellow box)"""
        return self._get_table_info() + self._get_avatar_info(
        ) + self._get_player_info()

    @catcher
    def _get_table_info(self):
        """returns a list of table informations"""
        highestbet = self.highestBetNotFold(),
        bigb = self.bigBlind(
        ) if self._game_state == GAME_STATE_PRE_FLOP and not self.inSmallBlindPosition(
        ) else 0
        return [
            "blinds: small:%r big:%r" % (self.small_blind, self.big_blind),
            "buy_ins: min:%r max:%r" % (self.min_buy_in, self.max_buy_in),
            "bs: %r" % self.betting_structure,
            "highestbet = %r" % highestbet,
            "bigb = %r" % bigb,
        ]

    @catcher
    def _get_player_info(self):
        """returns a list with player informations for all players"""
        return [player._player_info() for player in self.players.values()]

    @catcher
    def _get_avatar_info(self):
        """returns informations of the avatar that is currently logged in"""
        retvals = []
        if self.avatar.cards:
            retvals.append("hand: " + self._cards_to_string(self.avatar.cards))
        if self.board_cards:
            retvals.append("board: " + self._cards_to_string(self.board_cards))
            if self.avatar.cards:
                best_hand = self._eval.best_hand(
                    "hi",
                    self.avatar.getCards() + self.getBoardCards())
                desc = best_hand.pop(0)
                retvals.append("%s: %s" %
                               (desc, self._cards_to_string(best_hand)))
        return retvals
Пример #6
0
class Table(object):
    def __init__(self, protocol, avatar, table_info):
        self.protocol = protocol
        self.id = table_info.get('id', 0)
        self.seat = table_info.get('player_seated', -1)
        self.seats = [0] * table_info.get('seats', 10)
        if self.seat != -1:
            self.seats[self.seat] = avatar.serial
            assert avatar.seat == self.seat, "as %s, ss %s" % (avatar.seat, self.seat)
        self.name = table_info.get('name', 'unnamed')
        self.betting_structure =  table_info['betting_structure']
        blinds, buy_ins, limit = table_info['betting_structure'].split('_')
        min_buy_in, max_buy_in = buy_ins.split('-')
        small, big = blinds.split('-')

        self.max_buy_in = int(max_buy_in)*100
        self.min_buy_in = int(min_buy_in)*100
        self.big_blind = int(big)*100
        self.small_blind = int(small)*100

        self.players = {avatar.serial: avatar}
        self.avatar = avatar
        self._serial_and_game_id = dict(serial=avatar.serial, game_id=self.id)
        self._eval = PokerEval()
        self.reset()
        self._game_state = GAME_STATE_NULL

    def reset(self):
        """reseting game states for a new hand"""
        self.board_cards = []
        self.position = -1
        self._reset_players()

    def getBoardCards(self):
        """return a list of board games"""
        return list(map(lambda x:x&63, self.board_cards))

    def getAvatarInfo(self):
        """return a string of usefull information about the avatar"""
        return ", ".join(self._get_avatar_info())

    def isInPosition(self, serial):
        """returs true if player with serial is in position"""
        return serial in self.in_game and self.position == self.in_game.index(serial)

    def logIt(self, astr, prefix=" [D] "):
        """a little helper function to log output"""
        self.protocol.logIt(astr, prefix=prefix)

    def updateSeats(self, seats):
        """update seat information"""
        for index, (old, new) in enumerate(zip(self.seats, seats)):
            if old == 0 and new != 0:
                self.addPlayer(index, new)
            elif old != 0 and new == 0:
                self.removePlayer(index)
            elif old != new:
                self.removePlayer(index)
                self.addPlayer(index, new)
                self.logIt("warning idx %s, old %s, new %s" % (index, old, new))

    def addPlayer(self, index, serial):
        """Add player to this table"""
        self.seats[index] = serial
        # Request more information about this player
        if serial == self.avatar.serial:
            self.players[index] = self.avatar
        else:
            self.protocol.sendPacket(networkpackets.PacketPokerGetUserInfo(serial=serial))

    def removePlayer(self, index):
        """remove player from this table"""
        serial = self.seats[index]
        self.seats[index]=0
        if serial in self.players:
            del self.players[serial]

    def updatePlayer(self, player_info):
        """update general palyer information (we requested them in addPlayer)"""
        player = self._get_or_create_player(**player_info)
        player.update(player_info)

    def updatePlayerChips(self, serial, chips, bet):
        """update players chips"""
        player = self._get_or_create_player(serial=serial)
        return player.updateChips(chips, bet)

    def updatePlayerCards(self, serial, cards):
        """update players cards"""
        player = self._get_player(serial)
        player.updateCards(cards)

    def rebuy(self, serial, amount):
        """update money state of player because a rebuy happend"""
        player = self._get_player(serial)
        player.rebuy(amount)

    def _reset_players(self):
        """reset player states"""
        for player in self.players.values():
            player.reset()

    def highestBetNotFold(self):
        """returns the highest bet of all players that are not fold"""
        return max([0]+[p._bet for p in self.players.values() if p.serial in self.in_game and p.notFold()])
    
    def inSmallBlindPosition(self):
        """returns True if the player in position is in small_blind position"""
        return len(self.in_game) > 0 and ((self.dealer + 1) % len(self.in_game)) == self.position

    def bigBlind(self):
        """returns the big_blind of the current table"""
        return self.big_blind or 0

    def doBuyIn(self):
        """actually request a buy_in"""
        self.protocol.sendPacket(networkpackets.PacketPokerBuyIn(amount=self.max_buy_in, **self._serial_and_game_id))
        self.protocol.sendPacket(networkpackets.PacketPokerAutoBlindAnte(**self._serial_and_game_id))
    
    def doRebuy(self, amount):
        """actually request a rebuy"""
        self.protocol.sendPacket(networkpackets.PacketPokerRebuy(amount=amount, **self._serial_and_game_id))

    def doSit(self):
        """actually request a sit"""
        self.protocol.sendPacket(networkpackets.PacketPokerSit(**self._serial_and_game_id))
    
    def doSitOut(self):
        """actually request a sitout"""
        self.protocol.sendPacket(networkpackets.PacketPokerSitOut(**self._serial_and_game_id))
    
    def doQuit(self):
        """actually request a table quit"""
        self.protocol.sendPacket(networkpackets.PacketPokerTableQuit(**self._serial_and_game_id))
    
    def doFold(self):
        """actually request a fold"""
        self.protocol.sendPacket(networkpackets.PacketPokerFold(**self._serial_and_game_id))
    
    def doCheck(self):
        """actually request a check"""
        self.protocol.sendPacket(networkpackets.PacketPokerCheck(**self._serial_and_game_id))
    
    def doCall(self):
        """actually request a call"""
        self.protocol.sendPacket(networkpackets.PacketPokerCall(**self._serial_and_game_id))
    
    def doAllIn(self):
        """actually raise all chips"""
        self.doRaise(self.avatar.getChips())
    def doRaise(self, amount):
        """
            actually request a raise by a given amount.
            WARNING: If the amount you requested is too low, the raise will be accepted but the 
            minimum amount to raise will be used instead. You will be informend about the amount 
            that is used to raise.
        """
        self.protocol.sendPacket(networkpackets.PacketPokerRaise(amount=amount, **self._serial_and_game_id))
    

    def explain(self, packet, state):
        """packets that might be interesting for the game will be handled here"""
        def handlePacketPokerBuyInLimits(packet):
            self.max_buy_in = packet.max
            self.min_buy_in = packet.min
        def handlePacketPokerSeats(packet):
            return self.updateSeats(packet.seats)
        def handlePacketPokerPlayerInfo(packet):
            self.updatePlayer(packet.__dict__)
        def handlePacketPokerPlayerChips(packet):
            return self.updatePlayerChips(packet.serial, chips=packet.money, bet=packet.bet)
        def handlePacketPokerPlayerArrive(packet):
            self.updatePlayer(packet.__dict__)
        def handlePacketPokerPlayerLeave(packet):
            self.removePlayer(packet.seat)
        def handlePacketPokerSit(packet):
            self._get_player(packet.serial).sit()
        def handlePacketPokerSitOut(packet):
            self._get_player(packet.serial).sitOut()
        def handlePacketPokerRebuy(packet):
            assert self.id == packet.game_id
            self.rebuy(packet.serial, packet.amount)
        def handlePacketPokerInGame(packet):
            assert self.id == packet.game_id
            self.in_game = packet.players
        def handlePacketPokerPosition(packet):
            assert self.id == packet.game_id
            self.position = packet.position
        def handlePacketPokerStart(packet):
            assert self.id == packet.game_id
            self.reset()
            self.hand_serial = packet.hand_serial
        def handlePacketPokerDealer(packet):
            assert self.id == packet.game_id
            # assert self.dealer == packet.previous_dealer
            self.dealer = packet.dealer
        def handlePacketPokerPlayerCards(packet):
            self.updatePlayerCards(packet.serial, packet.cards)
            if packet.serial == self.avatar.serial:
                self.logIt("You got %r" % self._cards_to_string(packet.cards))
        def handlePacketPokerBoardCards(packet):
            self.board_cards = packet.cards
        def handlePacketPokerRaise(packet):
            self._get_player(packet.serial).bet(packet.amount)
        def handlePacketPokerCall(packet):
            player = self._get_player(packet.serial)
            highestbet = self.highestBetNotFold()
            bigb =self.bigBlind() if self._game_state == GAME_STATE_PRE_FLOP and not self.inSmallBlindPosition() else 0
            # import rpdb2; rpdb2.start_embedded_debugger("haha")
            self.logIt("%r, %r" % (highestbet,bigb))
            amount = min(
                max(highestbet,bigb) - player._bet,
                player.money
            )
            player.bet(amount)
        def handlePacketPokerState(packet):
            self._game_state = packet.string
        def handlePacketPokerBlind(packet):
            self._get_player(packet.serial).bet(packet.amount)

        try:
            handle = locals()["handle"+packet.__class__.__name__]
            return handle(packet)
        except KeyError:
            # self.logIt(" explain cant handle : %r" % packet.__class__.__name__)
            return True
        except Exception:
            exc_type, exc_value, exc_traceback = sys.exc_info()
            self.logIt(packet.__class__.__name__, prefix=" EEE  handle failed: ")

            for exline in traceback.format_exception(exc_type, exc_value,
                                          exc_traceback):
                for line in exline.split('\n'):
                    self.logIt(str(line), prefix=" EEE ")

    def _cards_to_string(self, cards):
        """return a string for cards in a human readable way"""
        return repr(self._eval.card2string(map(lambda x: x & 63, cards)))\
            #.lower().replace("h", u"\u2761").replace("s", u"\u2660").replace("c", u"\u2663").replace("d", u"\u2662")
    def _get_or_create_player(self, serial, seat=None, **player_info):
        """returns the player with the serial, the player will be created if it does not exist yet"""
        # serial = player_info['serial']
        # seat = player_info['seat']
        if seat and self.seats[seat] != 0 and serial != self.seats[seat]:
            self.logIt("%s is allready on seat %s, cleared" % (self.seats[seat], seat))
            del self.players[self.seats[seat]]
            self.seats[seat] = serial

        if serial not in self.players:
            self.players[serial] = Player(serial=serial, seat=seat, **player_info)

        return self.players[serial]
    
    def _get_player(self, serial):
        """returns the player, raises an IndexError if it does not exist"""
        return self.players[serial]

    def _log_players(self):
        """ log player informations """
        self.logIt("Players:")
        for player in self.players.itervalues():
            self.logIt(player._player_info())
        self.logIt("")

    
    def getDebugLines(self):
        """returns a list of debug lines (yellow box)"""
        return self._get_table_info() + self._get_avatar_info() + self._get_player_info()

    @catcher
    def _get_table_info(self):
        """returns a list of table informations"""
        highestbet = self.highestBetNotFold(),
        bigb =self.bigBlind() if self._game_state == GAME_STATE_PRE_FLOP and not self.inSmallBlindPosition() else 0
        return ["blinds: small:%r big:%r" % (self.small_blind, self.big_blind),
                "buy_ins: min:%r max:%r" % (self.min_buy_in, self.max_buy_in),
                "bs: %r" % self.betting_structure,
                "highestbet = %r" % highestbet,
                "bigb = %r" % bigb,]
    @catcher
    def _get_player_info(self):
        """returns a list with player informations for all players"""
        return [player._player_info() for player in self.players.values()]
    @catcher
    def _get_avatar_info(self):
        """returns informations of the avatar that is currently logged in"""
        retvals = []
        if self.avatar.cards:
            retvals.append("hand: " + self._cards_to_string(self.avatar.cards))
        if self.board_cards:
            retvals.append("board: " + self._cards_to_string(self.board_cards))
            if self.avatar.cards:
                best_hand = self._eval.best_hand("hi", self.avatar.getCards() + self.getBoardCards())
                desc = best_hand.pop(0)
                retvals.append("%s: %s" % (desc, self._cards_to_string(best_hand)))
        return retvals