def get_current_info(player, neighbors): #print(type(neighbors)) hand_map = {} invisible_tiles_map = Tile.get_tile_map(default_val=4) invisible_tiles_number = 36 * 3 + 7 * 4 for tile in player.hand: hand_map = utils.map_increment(hand_map, tile, 1) invisible_tiles_map = utils.map_increment(invisible_tiles_map, tile, -1) invisible_tiles_number -= 1 players = list(neighbors) + [player] for p in players: for _, _, tiles in p.fixed_hand: for tile in tiles: invisible_tiles_map = utils.map_increment( invisible_tiles_map, tile, -1) invisible_tiles_number -= 1 for tile in p.get_discarded_tiles("unstolen"): invisible_tiles_map = utils.map_increment(invisible_tiles_map, tile, -1) invisible_tiles_number -= 1 return hand_map, invisible_tiles_map, invisible_tiles_number
def decide_drop_tile(self, player, new_tile, neighbors, game): #print("BEGIN decide drop tile!!!!!") hand_map, invisible_tiles_map, invisible_tiles_number = get_current_info( player, neighbors) self.begin_decision() if self.display_step: self.print_game_board(player.fixed_hand, player.hand, neighbors, game, new_tile) drop_tile = new_tile if new_tile is not None else player.hand[0] rest_round = game.deck_size // 4 if rest_round > 0: fixed_hand = player.fixed_hand hand_map, invisible_tiles_map, invisible_tiles_number = get_current_info( player, neighbors) if new_tile is not None: hand_map = utils.map_increment(hand_map, new_tile, 1) invisible_tiles_map = utils.map_increment(invisible_tiles_map, new_tile, -1, remove_zero=True) invisible_tiles_number -= 1 root = node(fixed_hand, hand_map, invisible_tiles_map, invisible_tiles_number, rest_round, c=self._c, depth=0) root.expand_children() result = MCT_search(root, self._max_iteration) drop_tile = result self.print_msg("%s [%s] chooses to drop %s." % (self.player_name, display_name, drop_tile.symbol)) self.end_decision(True) return drop_tile
def MCT_rollout(node, action): ''' if type(action) == str and action =='end': # end node if node._possible_actions['end']['num_visit']==0: score = map_hand_eval_func(node.fixed_hand, node._hand_map, node._invisible_tiles_map, node._invisible_tiles_number) else: score = node._possible_actions['end']['avg_score'] else: ''' # simulation_node #print("Begin rollout") round_n = 0 hand_map = node._hand_map.copy() invisible_tiles_map = node._invisible_tiles_map.copy() invisible_tiles_number = node._invisible_tiles_number while node._depth + round_n < node._max_depth and invisible_tiles_number > 0: discard_tile = random.sample(hand_map.keys(), 1)[0] new_tile = random.sample(invisible_tiles_map.keys(), 1)[0] hand_map = utils.map_increment(hand_map, discard_tile, -1, remove_zero=True) invisible_tiles_map = utils.map_increment(invisible_tiles_map, new_tile, -1, remove_zero=True) invisible_tiles_number -= 1 hand_map = utils.map_increment(hand_map, new_tile, 1) round_n += 1 ## borrowed from github this eval_func score = map_hand_eval_func( node._fixed_hand, hand_map, invisible_tiles_map, invisible_tiles_number, random.sample(invisible_tiles_map.keys(), k=1)[0]) return score
def expand_children(self): if len(self._children) > 0: return try: for discard_tile in self._hand_map: self._possible_actions[discard_tile] = { 'list_childs': [], 'avg_score': 0, 'num_visit': 0, 'uct_score': 0 } # add child nodes for new_tile in self._invisible_tiles_map: hand_map = self._hand_map.copy() invisible_tiles_map = self._invisible_tiles_map.copy() invisible_tiles_number = self._invisible_tiles_number hand_map = utils.map_increment(hand_map, discard_tile, -1, remove_zero=True) invisible_tiles_map = utils.map_increment( invisible_tiles_map, new_tile, -1, remove_zero=True) invisible_tiles_number -= 1 hand_map = utils.map_increment(hand_map, new_tile, 1) child = node(self._fixed_hand, hand_map, invisible_tiles_map, invisible_tiles_number, self._max_depth, depth=self._depth + 1, parent=self, action=discard_tile) self._children[(discard_tile, new_tile)] = child self._possible_actions[discard_tile]['list_childs'].append( child) #self._possible_actions['end'] = {'list_childs': [], 'avg_score': 0, 'num_visit':0} self._expand = True except: pass
def decide_pong(self, player, new_tile, neighbors, game): #print("BEGIN decide pong!!!!!") self.begin_decision() if self.display_step: self.print_game_board(player.fixed_hand, player.hand, neighbors, game) self.print_msg("Someone just discarded a %s." % new_tile.symbol) result = False rest_round = game.deck_size // 4 if rest_round > 0: fixed_hand = player.fixed_hand hand_map, invisible_tiles_map, invisible_tiles_number = get_current_info( player, neighbors) invisible_tiles_map = utils.map_increment(invisible_tiles_map, new_tile, -1, remove_zero=True) invisible_tiles_number = invisible_tiles_number - 1 root = node(None, None, None, None, rest_round, c=self._c) pong_fixed_hand = list(fixed_hand) pong_map_hand = hand_map.copy() pong_map_remaining = invisible_tiles_map.copy() utils.map_increment(pong_map_hand, new_tile, -2, remove_zero=True) pong_fixed_hand.append( ("pong", False, (new_tile, new_tile, new_tile))) node1 = node(pong_fixed_hand, pong_map_hand, pong_map_remaining, invisible_tiles_number, rest_round, parent=root, depth=1, c=self._c) root.add_child(node1, True) node2 = node(player.fixed_hand, hand_map, invisible_tiles_map, invisible_tiles_number, rest_round, parent=root, depth=1, c=self._c) root.add_child(node2, False) result = MCT_search(root, self._max_iteration) self.end_decision() if result: self.print_msg("%s [%s] chooses to form a Pong %s%s%s." % (self.player_name, display_name, new_tile.symbol, new_tile.symbol, new_tile.symbol)) return True else: self.print_msg("%s [%s] chooses not to form a Pong %s%s%s." % (self.player_name, display_name, new_tile.symbol, new_tile.symbol, new_tile.symbol)) return False
def decide_kong(self, player, new_tile, kong_tile, location, src, neighbors, game): #print("BEGIN decide kong!!!!!") self.begin_decision() if self.display_step: self.print_game_board(player.fixed_hand, player.hand, neighbors, game) hand_map, invisible_tiles_map, invisible_tiles_number = get_current_info( player, neighbors) fixed_hand = player.fixed_hand rest_round = game.deck_size // 4 # add the possible action into root = node(None, None, None, None, rest_round, c=self._c) # To kong kong_fixed_hand = list(fixed_hand) kong_map_hand = hand_map.copy() kong_map_remaining = invisible_tiles_map.copy() kong_tile_remaining = invisible_tiles_number - 1 if location == "fixed_hand": utils.map_increment(kong_map_remaining, kong_tile, -1, remove_zero=True) for i in range(len(player.fixed_hand)): if kong_fixed_hand[i][0] == "pong" and kong_fixed_hand[i][2][ 0] == kong_tile: kong_fixed_hand[i] = ("kong", False, (kong_tile, kong_tile, kong_tile, kong_tile)) break else: is_secret = False if src == "steal": self.print_msg("Someone just discarded a %s." % kong_tile.symbol) utils.map_increment(kong_map_hand, kong_tile, -3, remove_zero=True) utils.map_increment(kong_map_remaining, kong_tile, -1, remove_zero=True) elif src == "draw": self.print_msg("You just drew a %s" % kong_tile.symbol) utils.map_increment(kong_map_hand, kong_tile, -3, remove_zero=True) utils.map_increment(kong_map_remaining, kong_tile, -1, remove_zero=True) elif src == "existing": self.print_msg("You have 4 %s in hand" % kong_tile.symbol) utils.map_increment(kong_map_hand, kong_tile, -4, remove_zero=True) utils.map_increment(kong_map_hand, new_tile, 1, remove_zero=True) utils.map_increment(kong_map_remaining, new_tile, -1, remove_zero=True) kong_fixed_hand.append(("kong", is_secret, (kong_tile, kong_tile, kong_tile, kong_tile))) result = False if game.deck_size // 4 > 0: node1 = node(kong_fixed_hand, kong_map_hand, kong_map_remaining, kong_tile_remaining, rest_round, depth=1, c=self._c, parent=root) root.add_child(node1, True) node2 = node(player.fixed_hand, hand_map, invisible_tiles_map, invisible_tiles_number, rest_round, depth=1, c=self._c, parent=root) root.add_child(node2, False) result = MCT_search(root, self._max_iteration) self.end_decision() if result: self.print_msg( "%s [%s] chooses to form a Kong %s%s%s%s." % (self.player_name, display_name, kong_tile.symbol, kong_tile.symbol, kong_tile.symbol, kong_tile.symbol)) return True else: self.print_msg( "%s [%s] chooses not to form a Kong %s%s%s%s." % (self.player_name, display_name, kong_tile.symbol, kong_tile.symbol, kong_tile.symbol, kong_tile.symbol)) return False
def decide_chow(self, player, new_tile, choices, neighbors, game): #print("BEGIN decide chow!!!!!") self.begin_decision() if self.display_step: self.print_game_board(player.fixed_hand, player.hand, neighbors, game) self.print_msg("Someone just discarded a %s. (%s)" % (new_tile.symbol, ", ".join( [str(choice) for choice in choices]))) best_choice = choices[0] choice_tag = 0 hand_map, invisible_tiles_map, invisible_tiles_number = get_current_info( player, neighbors) rest_round = game.deck_size // 4 # add the possible action into if rest_round > 0: root = node(None, None, None, None, rest_round) ## add not chow child: child_not_chow = node(player.fixed_hand, hand_map, invisible_tiles_map, invisible_tiles_number, rest_round, parent=root, c=self._c, depth=1) root.add_child(child_not_chow, -1) ## add chow choice child: ch = 0 for choice in choices: new_fixed_hand = player.fixed_hand.copy() new_hand_map = hand_map.copy() new_invisible_map = invisible_tiles_map.copy() new_invisible_num = invisible_tiles_number tiles_for_melds = [] for i in range(choice - 1, choice + 2): tile = new_tile.generate_neighbor_tile(i) tiles_for_melds.append(tile) if tile != new_tile: new_hand_map = utils.map_increment(new_hand_map, tile, -1, remove_zero=True) else: utils.map_increment(new_invisible_map, tile, -1, remove_zero=True) new_invisible_num -= 1 new_fixed_hand.append(("chow", False, tuple(tiles_for_melds))) new_child = node(new_fixed_hand, new_hand_map, new_invisible_map, new_invisible_num, rest_round, parent=root, c=self._c, depth=1) root.add_child(new_child, ch) ch += 1 choice_tag = MCT_search(root, max_simulation=self._max_iteration) self.end_decision() if choice_tag == -1: self.print_msg("%s [%s] chooses not to Chow." % (self.player_name, display_name)) return False, None else: chow_tiles_str = "" best_choice = choices[choice_tag] for i in range(best_choice - 1, best_choice + 2): chow_tiles_str += new_tile.generate_neighbor_tile(i).symbol self.print_msg( "%s [%s] chooses to Chow %s." % (self.player_name, display_name, chow_tiles_str)) return True, best_choice