Beispiel #1
0
    def do_triple_swap(self):
        before = self.board.evaluate()
        swaps = list(self.enumerate_all_swaps())
        try:
            for idx1, (swap1id1, swap1id2) in enumerate(swaps):
                self.swap(swap1id1, swap1id2)
                for idx2, swap2id1, swap2id2 in enumerate(swaps):
                    self.swap(swap2id1, swap2id2)
                    for idx3, swap3id1, swap3id2 in enumerate(swaps):
                        self.swap(swap3id1, swap3id2)
                        self.board.fix_orientation()
                        self.board.heuristic_orientation()

                        after = board.evaluate()
                        if after > before:
                            #print(f"triple swap success {swap1id1}{swap1id2}{swap2id1}{swap2id2}{swap3id1}{swap3id2} score {before} -> {after}")
                            raise Exception()

                        # third swap back
                        self.swap(swap3id1, swap3id2)
                    # second swap back
                    self.swap(swap2id1, swap2id2)
                # first swap back
                self.swap(swap1id1, swap1id2)
        except:
            # we find something, cool...
            self.board.fix_orientation()
            self.board.heuristic_orientation()
            return True

        return False
Beispiel #2
0
    def check_best():
        curr = board.evaluate()

        global best
        global shuffle_counter
        global shuffle_backup
        #
        # if shuffle_counter <= 0 and curr == best:
        #     # trying to find sequence of ANY 2 swaps that potentially increase the overall score ...
        #     #swapper.do_double_swap()
        #     shuffle_backup = copy.deepcopy(board)
        #     swapper.shuffle()
        #     shuffle_counter = 3

        #if True: # DEBUG TEST ONLY
        #if double_swap_counter <= 0 and curr == best:
        # if False: # double swapping disabled for now - until not optimized
        #     print("DOUBLE SWAP! Start...")
        #     # trying to find sequence of ANY 2 swaps that potentially increase the overall score ...
        #     #swapper.do_double_swap()
        #     swapper.do_double_swap()
        #     print("DOUBLE SWAP! End...")
        #     double_swap_counter = 3

        ui.update()
        if best < curr:
            print(f"[UI] Best score improved to {curr}")
            best = curr

            if best >= board.max_score() - 30:
                board.save("save " + str(uuid.uuid4()) + "_" + str(best) +
                           ".csv")
            # we fill in remaining pieces to have a slightly better score

            if best == board.max_score():
                pygame.display.set_caption(f'Puzzle SOLVED!')
                print("SOLVED!")
        # elif best == curr:
        #     double_swap_counter -= 1

        pygame.display.set_caption(
            f'SBest {best}/{board.max_score()} SCurr {curr}/{board.max_score()}'
        )
Beispiel #3
0
    start = time.time()
    running_min = 0
    running_sec = 0
    next_explored_stats_update = start
    explored_stats_rate = 5
    explored_str = ""

    best_replacer = replacer
    best_score_count_limit = 500
    best_score_counter = best_score_count_limit

    best = 0
    while True:
        replacer.step()
        ui.update()
        val = board.evaluate()
        if best < val:
            best_replacer = copy.deepcopy(replacer)
            #ui.board = best_board
            #ui.update()

            best = val
            # we fill in remaining pieces to have a slightly better score
            best_score_counter = best_score_count_limit
        else:
            best_score_counter -= 1

        if best_score_counter <= 0:
            best_score_counter = best_score_count_limit
            replacer = best_replacer
            ui.board = best_replacer.board
Beispiel #4
0
    def quick_swaps(self):
        before = self.board.evaluate()
        max_after = before
        max_indices = None

        same_indices = []

        CORNERS = 0
        EDGES = 1
        INNER = 2

        seq = [INNER, EDGES, CORNERS]
        random.shuffle(seq)

        try:
            for type in seq:
                if type == CORNERS:
                    # see how much we gain be swapping corners ...
                    corner_idxs = self.cached_corners_idxs
                    random.shuffle(corner_idxs)
                    # throw away hint pieces

                    evals = [
                        self.board.evaluate_piece(i, j) for i, j in corner_idxs
                    ]
                    evals, corner_idxs = zip(*sorted(zip(evals, corner_idxs)))

                    for idx1 in range(1, len(corner_idxs)):
                        for idx2 in range(idx1):
                            corner1 = corner_idxs[idx1]
                            corner2 = corner_idxs[idx2]

                            self.board.exchange(*corner1, *corner2)
                            self.board.marks[corner1[0]][corner1[1]], self.board.marks[corner2[0]][corner2[1]] = \
                                self.board.marks[corner2[0]][corner2[1]], self.board.marks[corner1[0]][corner1[1]]
                            self.board.fix_orientation()

                            after = board.evaluate()
                            if after > max_after:
                                max_after = after
                                max_indices = (corner1, corner2)
                                raise Exception()

                            if after == before:
                                same_indices.append((corner1, corner2))

                            self.board.exchange(*corner1, *corner2)
                            self.board.marks[corner1[0]][corner1[1]], self.board.marks[corner2[0]][corner2[1]] = \
                                self.board.marks[corner2[0]][corner2[1]], self.board.marks[corner1[0]][corner1[1]]

                elif type == EDGES:
                    # ... or by swapping edges ...
                    edge_idxs = self.cached_edge_idxs
                    random.shuffle(edge_idxs)
                    evals = [
                        self.board.evaluate_piece(i, j) for i, j in edge_idxs
                    ]
                    evals, edge_idxs = zip(*sorted(zip(evals, edge_idxs)))
                    for idx1 in range(1, len(edge_idxs)):
                        for idx2 in range(idx1):
                            edge1 = edge_idxs[idx1]
                            edge2 = edge_idxs[idx2]

                            self.board.exchange(*edge1, *edge2)
                            self.board.marks[edge1[0]][edge1[1]], self.board.marks[edge2[0]][edge2[1]] = \
                                self.board.marks[edge2[0]][edge2[1]], self.board.marks[edge1[0]][edge1[1]]
                            self.board.fix_orientation()
                            after = self.board.evaluate()
                            if after > max_after:
                                max_after = after
                                max_indices = (edge1, edge2)
                                raise Exception()

                            if after == before:
                                same_indices.append((edge1, edge2))

                            self.board.exchange(*edge1, *edge2)
                            self.board.marks[edge1[0]][edge1[1]], self.board.marks[edge2[0]][edge2[1]] = \
                                self.board.marks[edge2[0]][edge2[1]], self.board.marks[edge1[0]][edge1[1]]

                elif type == INNER:
                    # ... or by swapping inner pieces
                    inner_idxs = self.cached_inner_idxs
                    random.shuffle(inner_idxs)

                    # pick only those that have score < 4
                    actual_inner_idxs = []
                    evals = []
                    for i, j in inner_idxs:
                        val = self.board.evaluate_piece(i, j)
                        if val <= 4:
                            actual_inner_idxs.append((i, j))
                            evals.append(val)

                    # evals = [self.board.evaluate_piece(i,j) for i,j in inner_idxs]
                    evals, actual_inner_idxs = zip(
                        *sorted(zip(evals, actual_inner_idxs)))

                    for idx1 in range(1, len(actual_inner_idxs)):
                        inner1 = actual_inner_idxs[idx1]

                        for idx2 in range(idx1):
                            inner2 = actual_inner_idxs[idx2]

                            if evals[idx2] >= 4:
                                break

                            orig_dir1 = self.board.board[inner1[0]][
                                inner1[1]].dir
                            orig_dir2 = self.board.board[inner2[0]][
                                inner2[1]].dir
                            piece_score_before = self.board.evaluate_piece(
                                *inner1) + self.board.evaluate_piece(*inner2)

                            # if these pieces are next to each other and they share a color now,
                            # then we have over counted it
                            if self.have_common_edge(inner1, inner2):
                                piece_score_before -= 1

                            self.board.exchange(*inner1, *inner2)
                            self.board.marks[inner1[0]][inner1[1]], self.board.marks[inner2[0]][inner2[1]] = \
                                self.board.marks[inner2[0]][inner2[1]], self.board.marks[inner1[0]][inner1[1]]
                            piece_score_best_after = piece_score_before

                            for dir1 in range(4):
                                for dir2 in range(4):
                                    self.board.board[inner1[0]][
                                        inner1[1]].dir = dir1
                                    self.board.board[inner2[0]][
                                        inner2[1]].dir = dir2
                                    piece_score_after = self.board.evaluate_piece(
                                        *inner1)
                                    piece_score_after += self.board.evaluate_piece(
                                        *inner2)

                                    # if these pieces are next to each other and they share a color now,
                                    # then we have over counted it
                                    if self.have_common_edge(inner1, inner2):
                                        piece_score_after -= 1

                                    # after = board.evaluate()
                                    # if after > max_after:
                                    #     max_after = after
                                    #     max_indices = (inner1, inner2)
                                    #     raise Exception()

                                    # if after == before:
                                    #     same_indices.append((inner1, inner2))

                                    if piece_score_after > piece_score_best_after:
                                        #print(
                                        #    f"Switching {inner1} <-> {inner2}, score {piece_score_before} to {piece_score_after}")
                                        piece_score_best_after = piece_score_after
                                        self.board.heuristic_orientation()
                                        raise Exception()

                                    if piece_score_after == piece_score_before:
                                        same_indices.append((inner1, inner2))

                            self.board.exchange(*inner1, *inner2)
                            self.board.marks[inner1[0]][inner1[1]], self.board.marks[inner2[0]][inner2[1]] = \
                                self.board.marks[inner2[0]][inner2[1]], self.board.marks[inner1[0]][inner1[1]]

                            self.board.board[inner1[0]][
                                inner1[1]].dir = orig_dir1
                            self.board.board[inner2[0]][
                                inner2[1]].dir = orig_dir2

        except:
            # we find something, cool...
            self.board.fix_orientation()
            return True

        # If we've got here, nothing more to do
        #print("Can't find anything else...")

        if same_indices:
            # crazy variant, lets shuffle all the indicies we can -> temporaririly can decrease the score though
            random.shuffle(same_indices)
            for same_pair in same_indices[:10]:
                #print(f"... exchanging pieces {same_pair[0]} with {same_pair[1]} with same result to give chance of swing into another possibilities")
                board.exchange(*same_pair[0], *same_pair[1])
                board.marks[same_pair[0][0]][same_pair[0][1]], board.marks[same_pair[1][0]][same_pair[1][1]] = \
                    board.marks[same_pair[1][0]][same_pair[1][1]], board.marks[same_pair[0][0]][same_pair[0][1]]
            board.fix_orientation()
            board.heuristic_orientation()
            return True

            # same_pair = same_indices[random.randint(0, len(same_indices) - 1)]
            # print(f"... exchanging pieces {same_pair[0]} with {same_pair[1]} with same result to give chance of swing into another possibilities")
            # board.exchange(*same_pair[0], *same_pair[1])
            # board.marks[same_pair[0][0]][same_pair[0][1]], board.marks[same_pair[1][0]][same_pair[1][1]] = \
            #     board.marks[same_pair[1][0]][same_pair[1][1]], board.marks[same_pair[0][0]][same_pair[0][1]]
            # board.fix_orientation()
            # board.heuristic_orientation()
            # return True
        else:
            #print("... and no pieces with same score!")
            return False
Beispiel #5
0
                        if not board.board[i][j]:
                            board.put_piece(i, j, board.puzzle_def.all[id], 0)
                            break
                    pass
                elif board.puzzle_def.all[id].get_type() == TYPE_EDGE:
                    for i, j in board.enumerate_edges():
                        if not board.board[i][j]:
                            board.put_piece(i, j, board.puzzle_def.all[id], 0)
                            break
                else:  # INNER
                    for i, j in board.enumerate_inner():
                        if not board.board[i][j]:
                            board.put_piece(i, j, board.puzzle_def.all[id], 0)
                            break
        board.fix_orientation()
        board.evaluate()
    else:
        board.randomize()
        board.fix_orientation()
        board.heuristic_orientation()

    # mark the pieces
    for i in range(height):
        for j in range(width):
            if board.board[i][j]:
                board.marks[i][j] = board.board[i][j].piece_def.id

    swapper = Swapper(board)

    ui = ui.BoardUi(board)
    ui.init()