Beispiel #1
0
    def put_stone(self, log: List[Stone]) -> Stone:
        turn = turn_check(log, self.p, self.q)
        if len(log) == 0:
            return Stone(str(10), str(10), turn)

        if len(log) == 1:
            next_x = int(log[0].x) + choice([-1, 1])
            next_y = int(log[0].y) + choice([-1, 1])
            return Stone(str(next_x), str(next_y), turn)

        log_x = [int(stone.x) for stone in log]
        log_y = [int(stone.y) for stone in log]

        left_end = max(min(log_x) - self.k, 1)
        right_end = min(max(log_x) + self.k, self.m)
        upper_end = max(min(log_y) - self.k, 1)
        lower_end = min(max(log_y) + self.k, self.n)

        width = right_end - left_end + 1
        height = lower_end - upper_end + 1

        focus_area = np.zeros((height, width), dtype=int)
        for stone in log:
            normalize_row_index = int(stone.y) - upper_end
            normalize_column_index = int(stone.x) - left_end
            focus_area[
                normalize_row_index,
                normalize_column_index] = 1 if stone.color == "b" else -1

        horizontal = self.find_connection(focus_area, Direction.HORIZONTAL,
                                          left_end, upper_end)
        vertical = self.find_connection(focus_area, Direction.VERTICAL,
                                        left_end, upper_end)
        negative_diagonal = self.find_connection(focus_area,
                                                 Direction.NEGATIVE_DIAGONAL,
                                                 left_end, upper_end)
        positive_diagonal = self.find_connection(focus_area,
                                                 Direction.POSITIVE_DIAGONAL,
                                                 left_end, upper_end)
        candidates = horizontal + vertical + negative_diagonal + positive_diagonal
        if len(candidates) == 0:
            random_empty_spot = choice(self.empty_spots(log))
            return Stone(random_empty_spot.x, random_empty_spot.y, turn)

        max_stone = max(
            [self.stone_sum(candidate) for candidate in candidates])
        if max_stone >= self.k:
            return Stone("1", "1", turn)
        max_stone_candidates = [
            candidate for candidate in candidates
            if self.stone_sum(candidate) == max_stone
        ]
        max_stone_candidate = choice(max_stone_candidates)
        window_index = (sorted(
            [i for i, x in enumerate(max_stone_candidate.pattern) if x == 0],
            key=lambda x: abs(x - self.k / 2),
        )[0])
        position = max_stone_candidate.position[window_index]

        return Stone(str(position[0]), str(position[1]), turn)
Beispiel #2
0
 def put_stone(self, log: List[Stone]) -> Stone:
     turn = turn_check(log, self.p, self.q)
     if len(log) == 0:
         x = randint(1, self.n)
         y = randint(1, self.m)
         return Stone(str(x), str(y), turn)
     position = choice(self.suggest_positions(log))
     return Stone(position.x, position.y, turn)
Beispiel #3
0
    def move_stone(stone: Stone, direction: str, stride: int = 1) -> Stone:
        x = int(stone.x)
        y = int(stone.y)

        if direction == Direction.LEFT:
            x = x - stride
        elif direction == Direction.RIGHT:
            x = x + stride
        elif direction == Direction.UP:
            y = y - stride
        elif direction == Direction.DOWN:
            y = y + stride
        elif direction == Direction.UP_LEFT:
            y = y - stride
            x = x - stride
        elif direction == Direction.UP_RIGHT:
            y = y - stride
            x = x + stride
        elif direction == Direction.DOWN_LEFT:
            y = y + stride
            x = x - stride
        else:  # direction == Direction.DOWN_RIGHT:
            y = y + stride
            x = x + stride
        return Stone(str(x), str(y), stone.color)
Beispiel #4
0
 def empty_spots(self, log: List[Stone]) -> List[Stone]:
     full_area = np.zeros((self.n, self.m), dtype=int)
     for item in log:
         full_area[int(item.y) - 1, int(item.x) - 1] = 1
     empty_spot_index = np.where(full_area == 0)
     empty_spot_list = []
     for coordinate in list(zip(empty_spot_index[0], empty_spot_index[1])):
         empty_spot_list.append(
             Stone(str(coordinate[1] + 1), str(coordinate[0] + 1), "empty"))
     return empty_spot_list
Beispiel #5
0
 def check_diagonal_by_direction(current_stone: Stone,
                                 stone_history: List[Stone],
                                 radius: int,
                                 directions,
                                 ) -> bool:
     direction_list = [Stone(current_stone.x, current_stone.y, current_stone.color)]
     for direction in directions:
         current_x, current_y = int(current_stone.x), int(current_stone.y)
         for i in range(radius - 1):
             new_x, new_y = direction(current_x, current_y)
             direction_list.append(Stone(str(new_x), str(new_y), current_stone.color))
             current_x, current_y = new_x, new_y
     in_position = []
     for item in sorted(direction_list, key=lambda s: int(s.x)):
         if item in stone_history:
             in_position.append("1")
         else:
             in_position.append("0")
     in_position_concat = "".join(in_position)
     return "1" * radius in in_position_concat
Beispiel #6
0
    def suggest_positions(self,
                          log: List[Stone],
                          lower: int = 1,
                          upper: int = 19) -> List[Stone]:
        suggestions = []
        for d in Direction.ALL_DIRECTIONS:
            position = list(map(lambda x: self.move_stone(x, d, 1), log))
            position = list(
                filter(
                    lambda x: lower <= int(x.x) <= upper and lower <= int(x.y)
                    <= upper, position))
            suggestions = suggestions + position

        suggestions = set(map(lambda x: x.x + " " + x.y, suggestions))
        suggestions = list(map(lambda x: x.split(" "), suggestions))
        suggestions = list(map(lambda z: Stone(z[0], z[1], "s"), suggestions))
        stone_array = self.stone_to_array(log)
        suggestions = self.stone_to_array(suggestions)
        suggestions = np.clip(stone_array + suggestions, -1, 0)
        suggestions = self.array_to_stone(suggestions, "s")
        return suggestions
Beispiel #7
0
    def search(self, board, net, simulate_num, T, add_dirichlet_noise):
        logger.info("Search start!")
        for i in range(simulate_num):
            logger.info("simulate %s" % i)
            cp_board = copy.deepcopy(board)
            logger.info("root %s" % cp_board)

            # move to leaf
            node = self.root
            is_done, winner = None, None
            while not node.is_leaf():
                node, action = node.select()
                logger.info("select action: %s, select node info: %s" %
                            (action, node))
                pos = (action // conf.board_size, action % conf.board_size)
                is_done, winner = cp_board.step(Stone(pos, cp_board.turn))
                logger.info("board %s" % cp_board)
            if is_done:
                if winner is None:
                    v = 0
                else:
                    v = winner
                logger.info("Get done leaf, v: %s" % v)
            else:
                ps, v = net.predict(np.array([cp_board.get_feature()]))
                logger.info("Get leaf, v: %s" % v)
                if add_dirichlet_noise and i == 0:
                    ps = self.dirichlet_noise(ps)
                for idx in cp_board.illegal_idx:
                    ps[idx] = 0
                ps /= sum(ps)
                node.expand(ps=ps, player=cp_board.turn)
            node.backup(v)
        ret = [0] * conf.board_size**2
        for idx, child in self.root.children.items():
            ret[idx] = child.N
        return np.array(ret)**(1.0 / T) / sum(np.array(ret)**(1.0 / T))
Beispiel #8
0
def play():
    x = request.args.get("x")
    y = request.args.get("y")
    color = request.args.get("color")

    if regex_digit.match(x) is None:
        return {"code": 400, "message": "illegal input in x"}, 400

    if regex_digit.match(y) is None:
        return {"code": 400, "message": "illegal input in y"}, 400

    if regex_color.match(color) is None:
        return {"code": 400, "message": "illegal input in stone"}, 400

    if color != util.turn_check(board.log, board.config.each_move,
                                board.config.first_move):
        board.print_illegal_turn()
        board.save_figure()
        return render_template("board.html")

    stone = Stone(x, y, color)
    if not referee.valid_check(stone, board.log):
        board.print_illegal_stone()
        board.save_figure()
        return render_template("board.html")

    board.put_stone(stone)
    end_check = referee.end_check(board.log, board.config)
    if end_check.is_end:
        winner = "no one" if end_check.is_tie else color
        board.print_winner(winner)
        board.save_figure()
        return render_template("board.html")

    board.print_on_playing()
    board.save_figure()
    return render_template("board.html")
Beispiel #9
0
 def __init__(self, *args, **kwargs):
     super(StrategicBotTest, self).__init__(*args, **kwargs)
     self.test_config = BoardConfig(19, 19, 6, 2, 1)
     self.vertical_test_log = [
         Stone("3", "2", "b"),
         Stone("2", "1", "w"),
         Stone("2", "2", "w"),
         Stone("1", "2", "b"),
         Stone("1", "3", "b"),
         Stone("2", "3", "w"),
         Stone("2", "4", "w"),
         Stone("1", "4", "b"),
         Stone("1", "5", "b"),
         Stone("2", "5", "w"),
         Stone("2", "8", "w"),
         Stone("1", "10", "b"),
         Stone("1", "11", "b"),
         Stone("2", "9", "w"),
     ]
     self.diagonal_test_log = [
         Stone("1", "2", "b"),
         Stone("1", "1", "w"),
         Stone("2", "2", "w"),
         Stone("1", "3", "b"),
         Stone("1", "4", "b"),
         Stone("3", "3", "w"),
         Stone("4", "4", "w"),
         Stone("1", "5", "b"),
         Stone("1", "8", "b"),
         Stone("5", "5", "w"),
         Stone("8", "4", "w"),
         Stone("7", "10", "b"),
         Stone("8", "10", "b"),
         Stone("9", "11", "w"),
         Stone("6", "7", "w"),
         Stone("4", "10", "b"),
         Stone("5", "10", "b"),
         Stone("7", "5", "w"),
     ]
     self.sb = StrategicBot(self.test_config)
Beispiel #10
0
        suggestions = self.array_to_stone(suggestions, "s")
        return suggestions

    def put_stone(self, log: List[Stone]) -> Stone:
        turn = turn_check(log, self.p, self.q)
        if len(log) == 0:
            x = randint(1, self.n)
            y = randint(1, self.m)
            return Stone(str(x), str(y), turn)
        position = choice(self.suggest_positions(log))
        return Stone(position.x, position.y, turn)


if __name__ == "__main__":
    diagonal_test_log = [
        Stone("1", "2", "b"),
        Stone("1", "1", "w"),
        Stone("2", "2", "w"),
        Stone("1", "3", "b"),
        Stone("1", "4", "b"),
        Stone("3", "3", "w"),
        Stone("4", "4", "w"),
        Stone("1", "5", "b"),
        Stone("1", "6", "b"),
        Stone("5", "5", "w"),
        Stone("6", "5", "w"),
        Stone("10", "11", "b"),
        Stone("11", "11", "b"),
        Stone("6", "6", "w"),
    ]
    def play_a_agme(self, net, paint=False):
        logger.info("New game start!")
        steps = 0
        board = Board()
        mcts = MCTS()
        data = []
        ps = []
        while True:
            feature = board.get_feature()
            p = mcts.search(
                board=board,
                net=net,
                simulate_num=conf.simulate_num,
                T=1 if steps < conf.explore_steps else 0.5,
                add_dirichlet_noise=True,
            )

            debug_ps, debug_v = net.predict(np.array([feature]))
            logger.info("V: %s" % debug_v)
            info = ''
            info += "NetWork predict probs:\n"
            for i in range(1, len(debug_ps) + 1):
                info += "%.3f" % debug_ps[i - 1] + ' '
                if i % conf.board_size == 0:
                    info += '\n'
            logger.info(info)

            info = ''
            info += "MCTS search probs:\n"
            for i in range(1, len(p) + 1):
                info += "%.3f" % p[i - 1] + ' '
                if i % conf.board_size == 0:
                    info += '\n'
            logger.info(info)

            data.append(feature)
            ps.append(p)

            idx = np.random.choice(conf.board_size ** 2, p=p)
            pos = (idx // conf.board_size, idx % conf.board_size)
            mcts.change_root(idx)
            stone = Stone(pos, board.turn)
            is_done, winner = board.step(stone)
            steps += 1
            if paint:
                logger.info(board)
            if is_done:
                if paint:
                    if winner == Player.O:
                        logger.info("O WIN!")
                    elif winner == Player.X:
                        logger.info("X WIN!")
                    else:
                        logger.info("NO WINNER!")
                if winner == Player.O:
                    vs = [Player.O] * len(data)
                elif winner == Player.X:
                    vs = [Player.X] * len(data)
                else:
                    vs = [0] * len(data)
                return self.data_augmentation(
                    zip(data, ps, vs)
                )
Beispiel #12
0
    def empty_spots(self, log: List[Stone]) -> List[Stone]:
        full_area = np.zeros((self.n, self.m), dtype=int)
        for item in log:
            full_area[int(item.y) - 1, int(item.x) - 1] = 1
        empty_spot_index = np.where(full_area == 0)
        empty_spot_list = []
        for coordinate in list(zip(empty_spot_index[0], empty_spot_index[1])):
            empty_spot_list.append(
                Stone(str(coordinate[1] + 1), str(coordinate[0] + 1), "empty"))
        return empty_spot_list


if __name__ == "__main__":
    vertical_test_log = [
        Stone("3", "2", "b"),
        Stone("2", "1", "w"),
        Stone("2", "2", "w"),
        Stone("1", "2", "b"),
        Stone("1", "3", "b"),
        Stone("2", "3", "w"),
        Stone("2", "4", "w"),
        Stone("1", "4", "b"),
        Stone("1", "5", "b"),
        Stone("2", "5", "w"),
        Stone("2", "8", "w"),
        Stone("1", "10", "b"),
        Stone("1", "11", "b"),
        Stone("2", "9", "w"),
    ]
    diagonal_test_log = [
Beispiel #13
0
 def player_input(color: str) -> Stone:
     x = input("x: ")
     y = input("y: ")
     return Stone(x, y, color)
Beispiel #14
0
        if len(log) == 0:
            x = randint(1, self.n)
            y = randint(1, self.m)
            return Stone(str(x), str(y), turn)
        elif len(self.suggest_positions(log)) > 0:
            position = choice(self.suggest_positions(log))
        else:
            x = randint(1, self.n)
            y = randint(1, self.m)
            return Stone(str(x), str(y), turn)
        return Stone(position.x, position.y, turn)


if __name__ == "__main__":
    diagonal_test_log = [
        Stone("1", "2", "b"),
        Stone("1", "1", "w"),
        Stone("2", "2", "w"),
        Stone("1", "3", "b"),
        Stone("1", "4", "b"),
        Stone("3", "3", "w"),
        Stone("4", "4", "w"),
        Stone("1", "5", "b"),
        Stone("1", "6", "b"),
        Stone("5", "5", "w"),
        Stone("7", "5", "w"),
        Stone("10", "11", "b"),
        Stone("11", "11", "b"),
        Stone("6", "6", "w"),
    ]
Beispiel #15
0
                direction_list.append(Stone(str(new_x), str(new_y), current_stone.color))
                current_x, current_y = new_x, new_y
        in_position = []
        for item in sorted(direction_list, key=lambda s: int(s.x)):
            if item in stone_history:
                in_position.append("1")
            else:
                in_position.append("0")
        in_position_concat = "".join(in_position)
        return "1" * radius in in_position_concat


if __name__ == "__main__":
    test_board_config = BoardConfig(19, 19, 6, 2, 1)
    test_log = [
        Stone("1", "1", "b"),
        Stone("2", "1", "w"),
        Stone("2", "2", "w"),
        Stone("1", "2", "b"),
        Stone("1", "3", "b"),
        Stone("2", "3", "w"),
        Stone("2", "4", "w"),
        Stone("1", "4", "b"),
        Stone("1", "5", "b"),
        Stone("2", "5", "w"),
        Stone("2", "8", "w"),
        Stone("1", "10", "b"),
        Stone("1", "11", "b"),
        Stone("2", "9", "w"),
        Stone("2", "6", "w"),
    ]
Beispiel #16
0
 def random_bot(self, color: str) -> Stone:
     x = randint(1, self.config.column)
     y = randint(1, self.config.row)
     return Stone(str(x), str(y), color)