Exemplo n.º 1
0
 def _handle_newhand(self, data):
     hand_num = int(data[1])
     big_blind = data[2] == 'false'
     self.current_cards = data[3].split(',')
     bankroll = int(data[4])
     opponent_bankroll = int(data[5])
     self.move_history = []
     self.current_pot = Pot(
         **{
             'pip':
             self.current_game.
             big_blind if big_blind else self.current_game.big_blind / 2,
             'bets':
             0,
             'opponent_bets':
             self.current_game.
             big_blind if not big_blind else self.current_game.big_blind /
             2,
             'num_exchanges':
             0,
             'opponent_num_exchanges':
             0
         })
     self.current_round = Round(hand_num, bankroll, opponent_bankroll,
                                big_blind)
     self.bot.handle_new_round(self.current_game, self.current_round)
Exemplo n.º 2
0
    def _update_pot(self, new_moves, new_pot_total):
        new_pot = self.current_pot._asdict()
        for move in new_moves:
            if move.startswith('EXCHANGE') and move.split(':')[-1] == self.current_game.opponent_name:
                new_pot['opponent_num_exchanges'] += 1
            elif move.startswith('DEAL') or move.startswith('TIE') or move.startswith('WIN'):
                new_pot['bets'] += new_pot['pip']
                new_pot['pip'] = 0

        new_pot['opponent_bets'] = new_pot_total - self.current_pot.total - Pot(**new_pot).opponent_exchanges
        self.current_pot = Pot(**new_pot)
Exemplo n.º 3
0
    def _handle_action(self, action):
        new_pot = self.current_pot._asdict()

        if isinstance(action, CheckAction):
            self.send('CHECK')
        elif isinstance(action, FoldAction):
            self.send('FOLD')
        elif isinstance(action, ExchangeAction):
            new_pot['num_exchanges'] += 1
            self.send('EXCHANGE')
        elif isinstance(action, CallAction):
            new_pot['pip'] += self._cost(action)
            self.send('CALL')
        elif isinstance(action, RaiseAction):
            new_pot['pip'] += self._cost(action)
            self.send('RAISE:{}'.format(action.amount))
        elif isinstance(action, BetAction):
            new_pot['pip'] += self._cost(action)
            self.send('BET:{}'.format(action.amount))

        self.current_pot = Pot(**new_pot)
Exemplo n.º 4
0
class Runner(object):
    def __init__(self, bot, socketfile, verbose):
        self.bot = bot
        self.socketfile = socketfile
        self.verbose = verbose
        self.current_game = None
        self.current_round = None
        self.current_cards = None
        self.current_pot = None
        self.move_history = []

    def receive(self):
        while True:
            packet = self.socketfile.readline().strip()

            if not packet:
                if self.verbose:
                    print("Gameover, engine disconnected.")
                break

            if self.verbose:
                print("==> {}".format(packet))

            yield packet

    def send(self, outgoing_string):
        if self.verbose:
            print("<== {}".format(outgoing_string))

        self.socketfile.write("{}\n".format(outgoing_string))
        self.socketfile.flush()

    def run(self):
        for packet in self.receive():
            data = packet.split(' ')
            action = data[0]

            if action == 'NEWGAME':
                self._handle_newgame(data)
            elif action == 'NEWHAND':
                self._handle_newhand(data)
            elif action == 'EXCHANGE':
                self._handle_exchange(data)
            elif action == 'GETACTION':
                action = self._handle_getaction(data)
                self._handle_action(action)
            elif action == 'HANDOVER':
                self._handle_handover(data)
            elif action == 'REQUESTKEYVALUES':
                # Ignore this, since we don't allow it anymore.
                self.send("FINISH")
            else:
                if verbose:
                    print("# Unexpected action: {}".format(action))

    def _handle_newgame(self, data):
        self.__init__(self.bot, self.socketfile, self.verbose)
        name = data[1]
        opponent_name = data[2]
        round_stack = int(data[3])
        big_blind = int(data[4])
        num_hands = int(data[5])
        time_bank = float(data[6])
        self.current_game = Game(name, opponent_name, round_stack, big_blind,
                                 num_hands, time_bank)
        self.bot.handle_new_game(self.current_game)

    def _handle_newhand(self, data):
        hand_num = int(data[1])
        big_blind = data[2] == 'false'
        self.current_cards = data[3].split(',')
        bankroll = int(data[4])
        opponent_bankroll = int(data[5])
        self.move_history = []
        self.current_pot = Pot(
            **{
                'pip':
                self.current_game.
                big_blind if big_blind else self.current_game.big_blind / 2,
                'bets':
                0,
                'opponent_bets':
                self.current_game.
                big_blind if not big_blind else self.current_game.big_blind /
                2,
                'num_exchanges':
                0,
                'opponent_num_exchanges':
                0
            })
        self.current_round = Round(hand_num, bankroll, opponent_bankroll,
                                   big_blind)
        self.bot.handle_new_round(self.current_game, self.current_round)

    def _handle_exchange(self, data):
        self.current_cards = data[2].split(',')

    def _get_legal_moves(self, legal_move_string):
        legal_move_strings = legal_move_string.split(';')
        min_amount = None
        max_amount = None
        legal_moves = set([])
        for move_string in legal_move_strings:
            if move_string.startswith('CHECK'):
                legal_moves.add(CheckAction)
            elif move_string.startswith('CALL'):
                legal_moves.add(CallAction)
            elif move_string.startswith('FOLD'):
                legal_moves.add(FoldAction)
            elif move_string.startswith('EXCHANGE'):
                legal_moves.add(ExchangeAction)
            elif move_string.startswith('RAISE'):
                legal_moves.add(RaiseAction)
            elif move_string.startswith('BET'):
                legal_moves.add(BetAction)

            if move_string.startswith('RAISE') or move_string.startswith(
                    'BET'):
                move_info = move_string.split(':')
                min_amount = int(move_info[1])
                max_amount = int(move_info[2])
        return legal_moves, min_amount, max_amount

    def _check_move_validity(self, action, legal_moves, min_amount,
                             max_amount):
        if type(action) not in legal_moves:
            return False

        if isinstance(action, RaiseAction) or isinstance(action, BetAction):
            return min_amount <= action.amount <= max_amount

        return True

    def _cost(self, action):
        if isinstance(action, CheckAction):
            return 0
        elif isinstance(action, CallAction):
            return self.current_pot.opponent_bets - self.current_pot.bets - self.current_pot.pip
        elif isinstance(action, FoldAction):
            return 0
        elif isinstance(action, ExchangeAction):
            return 2**(self.current_pot.num_exchanges + 1)
        elif isinstance(action, RaiseAction):
            return action.amount - self.current_pot.pip
        elif isinstance(action, BetAction):
            return action.amount - self.current_pot.pip

    def _update_pot(self, new_moves, new_pot_total):
        new_pot = self.current_pot._asdict()
        for move in new_moves:
            if move.startswith('EXCHANGE') and move.split(
                    ':')[-1] == self.current_game.opponent_name:
                new_pot['opponent_num_exchanges'] += 1
            elif move.startswith('DEAL') or move.startswith(
                    'TIE') or move.startswith('WIN'):
                new_pot['bets'] += new_pot['pip']
                new_pot['pip'] = 0

        new_pot[
            'opponent_bets'] = new_pot_total - self.current_pot.total - Pot(
                **new_pot).opponent_exchanges
        self.current_pot = Pot(**new_pot)

    def _handle_getaction(self, data):
        new_pot_total = int(data[1])
        new_moves = data[5].split(';')
        self._update_pot(new_moves, new_pot_total)
        self.move_history.extend(new_moves)
        board = [] if data[3] == 'None' else data[3].split(',')
        legal_moves, min_amount, max_amount = self._get_legal_moves(data[7])

        time_left = float(data[8])

        action = self.bot.get_action(self.current_game,
                                     self.current_round,
                                     self.current_pot,
                                     self.current_cards,
                                     board,
                                     legal_moves,
                                     self._cost,
                                     self.move_history,
                                     time_left,
                                     min_amount=min_amount,
                                     max_amount=max_amount)

        if isinstance(action, BetAction) or isinstance(action, RaiseAction):
            action = type(action)(amount=int(action.amount))

        if not self._check_move_validity(action, legal_moves, min_amount,
                                         max_amount):
            print(
                "Error: bot returned invalid move. Move: {}. Legal: {}, Min={}, Max={}"
                .format(action, legal_moves, min_amount, max_amount))
            if FoldAction in legal_moves:
                action = FoldAction()
            else:
                action = CheckAction()

        return action

    def _handle_action(self, action):
        new_pot = self.current_pot._asdict()

        if isinstance(action, CheckAction):
            self.send('CHECK')
        elif isinstance(action, FoldAction):
            self.send('FOLD')
        elif isinstance(action, ExchangeAction):
            new_pot['num_exchanges'] += 1
            self.send('EXCHANGE')
        elif isinstance(action, CallAction):
            new_pot['pip'] += self._cost(action)
            self.send('CALL')
        elif isinstance(action, RaiseAction):
            new_pot['pip'] += self._cost(action)
            self.send('RAISE:{}'.format(action.amount))
        elif isinstance(action, BetAction):
            new_pot['pip'] += self._cost(action)
            self.send('BET:{}'.format(action.amount))

        self.current_pot = Pot(**new_pot)

    def _get_result(self, new_moves):
        opponent_cards = None
        for move in new_moves:
            if move.startswith("SHOW") and move.endswith(
                    self.current_game.opponent_name):
                move_info = move.split(":")
                opponent_cards = move_info[1:3]
            elif move.startswith("TIE"):
                return 'tie', opponent_cards
            elif move.startswith("WIN"):
                if move.endswith(self.current_game.name):
                    return 'win', opponent_cards
                else:
                    return 'loss', opponent_cards
        return None, None

    def _handle_handover(self, data):
        bankroll = int(data[1])
        opponent_bankroll = int(data[2])
        board_cards = [] if data[4] == 'None' else data[4].split(',')
        new_moves = data[6].split(';')
        new_pot_total = int(data[7])
        self._update_pot(new_moves, new_pot_total)
        result, opponent_cards = self._get_result(new_moves)
        self.move_history.extend(new_moves)
        self.bot.handle_round_over(self.current_game, self.current_round,
                                   self.current_pot, self.current_cards,
                                   opponent_cards, board_cards, result,
                                   bankroll, opponent_bankroll,
                                   self.move_history)