def _init_bucketing(self): ''' Initializes the tensor that translates hand ranges to bucket ranges. ''' self.bucketer = Bucketer() self.bucket_count = self.bucketer.get_bucket_count() boards = card_tools.get_second_round_boards() self.board_count = boards.shape[0] CC, BC, bC = game_settings.card_count, self.board_count, self.bucket_count self._range_matrix = np.zeros([CC, BC * bC], dtype=arguments.dtype) self._range_matrix_board_view = self._range_matrix.reshape( [CC, BC, bC]) for idx in range(BC): board = boards[idx] buckets = self.bucketer.compute_buckets(board) class_ids = np.arange(bC) class_ids = class_ids.reshape([1, bC]) * np.ones( [CC, bC], dtype=class_ids.dtype) card_buckets = buckets.reshape([CC, 1]) * np.ones( [CC, bC], dtype=class_ids.dtype) # finding all strength classes # matrix for transformation from card ranges to strength class ranges self._range_matrix_board_view[:, idx, :][class_ids == card_buckets] = 1 # matrix for transformation from class values to card values self._reverse_value_matrix = self._range_matrix.T.copy() # we need to div the matrix by the sum of possible boards # (from point of view of each hand) weight_constant = 1 / (BC - 2) # count self._reverse_value_matrix *= weight_constant
def _get_children_nodes_chance_node(self, parent_node): ''' Creates the children nodes after a chance node. @param: parent_node the chance node @return a list of children nodes ''' assert (parent_node.current_player == constants.players.chance) if self.limit_to_street: return [] next_boards = card_tools.get_second_round_boards() # (N,K), K = 1 subtree_height = -1 # ? children = [] # 1.0 iterate over the next possible boards to build the corresponding subtrees for i in range(next_boards.shape[0]): next_board = next_boards[i] # ex: [4] next_board_string = card_to_string.cards_to_string(next_board) child = Node() child.node_type = constants.node_types.inner_node child.parent = parent_node child.current_player = constants.players.P1 child.street = parent_node.street + 1 child.board = next_board child.board_string = next_board_string child.bets = parent_node.bets.copy() children.append(child) return children
def _set_call_matrix(self, board): street = card_tools.board_to_street(board) self.equity_matrix = arguments.Tensor( game_settings.card_count, game_settings.card_count).zero_() if street == 0: #iterate through all possible next round streetss next_round_boards = card_tools.get_second_round_boards() boards_count = next_round_boards.size(0) next_round_equity_matrix = arguments.Tensor( game_settings.card_count, game_settings.card_count) for board in range(boards_count): self.get_last_round_call_matrix(next_round_boards[board], next_round_equity_matrix) self.equity_matrix.add_(next_round_equity_matrix) #averaging the values in the call matrix weight_constant = game_settings.board_card_count == 1 and 1 / ( game_settings.card_count - 2) or 2 / ( (game_settings.card_count - 2) * (game_settings.card_count - 3)) self.equity_matrix.mul_(weight_constant) elif street == 1: #for last round we just return the matrix self.get_last_round_call_matrix(board, self.equity_matrix) else: #impossible street assert (False) #, 'impossible street');
def _set_call_matrix(self, board): ''' Sets the evaluator's call matrix, which gives the equity for terminal nodes where no player has folded. For nodes in the last betting round, creates the matrix `A` such that for player ranges `x` and `y`, `x'Ay` is the equity for the first player when no player folds. For nodes in the first betting round, gives the weighted average of all such possible matrices. @param: board a possibly empty vector of board cards ''' CC = game_settings.card_count BCC = game_settings.board_card_count street = card_tools.board_to_street(board) self.equity_matrix = np.zeros([CC, CC], dtype=arguments.dtype) if street == 1: # iterate through all possible next round streets next_round_boards = card_tools.get_second_round_boards() next_round_equity_matrix = np.zeros(self.equity_matrix.shape, dtype=arguments.dtype) for board in range(next_round_boards.shape[0]): next_board = next_round_boards[board] self.get_last_round_call_matrix(next_board, next_round_equity_matrix) self.equity_matrix += next_round_equity_matrix # averaging the values in the call matrix weight_constant = 1 / (CC - 2) if BCC == 1 else 2 / ( (CC - 2) * (CC - 3)) # ? # tas pats: weight_constant = BCC == 1 and 1/(CC-2) or 2/((CC-2)*(CC-3)) self.equity_matrix *= weight_constant elif street == 2: # for last round we just return the matrix self.get_last_round_call_matrix(board, self.equity_matrix) else: assert (False, 'impossible street')
def _get_children_nodes_chance_node(self, parent_node): assert (parent_node.current_player == constants.players.chance) if self.limit_to_street: return [] next_boards = card_tools.get_second_round_boards() next_boards_count = next_boards.size(0) subtree_height = -1 children = [] #mjb the chance node's child differ with the different board card #1.0 iterate over the next possible boards to build the corresponding subtrees for i in range(next_boards_count): next_board = next_boards[i] next_board_string = card_to_string.cards_to_string(next_board) child = Node() self.node_id_acc = self.node_id_acc + 1 child.node_id = self.node_id_acc child.node_type = constants.node_types.inner_node child.parent = parent_node child.current_player = constants.players.P1 child.street = parent_node.street + 1 child.board = next_board child.board_string = next_board_string child.bets = parent_node.bets.clone() children.append(child) return children
def __init__(self): ''' Creates an equity matrix with entries for every possible pair of buckets. ''' self.bucketer = Bucketer() self.bucket_count = self.bucketer.get_bucket_count() bC, CC = self.bucket_count, game_settings.card_count self.equity_matrix = np.zeros([bC, bC], dtype=arguments.dtype) # filling equity matrix boards = card_tools.get_second_round_boards() self.board_count = boards.shape[0] self.terminal_equity = TerminalEquity() for i in range(self.board_count): board = boards[i] self.terminal_equity.set_board(board) call_matrix = self.terminal_equity.get_call_matrix() buckets = self.bucketer.compute_buckets(board) for c1 in range(CC): for c2 in range(CC): b1 = buckets[c1] b2 = buckets[c2] if b1 > 0 and b2 > 0: matrix_entry = call_matrix[c1][c2] self.equity_matrix[b1, b2] = matrix_entry