Beispiel #1
0
    def test_get_next_turn_only_success(self):

        success, new_board,  = SolutionChecker.get_next_turn(
            self.state, self.tile, val=1, get_only_success=True, destroy_state=True
        )

        # assert board is destroyed i.e. equal to new_board
        self.assertIsNone(new_board)
Beispiel #2
0
    def test_get_next_turn_destroy_board(self):

        success, new_board,  = SolutionChecker.get_next_turn(
            self.state, self.tile, val=1, get_only_success=False, destroy_state=True
        )
        self.assertEqual(success, True)

        # assert board is destroyed i.e. equal to new_board
        np.testing.assert_array_equal(
            self.state.board,
            new_board
        )
Beispiel #3
0
    def perform_simulation(self, state):
        '''
        Performs the simulation until legal moves are available.
        If simulation ends by finding a solution, a root state starting from this simulation is returned
        '''

        solution_tiles_order = []
        depth = 0
        simulation_root_state = state  # in case simulation ends in solution; these states are the solution
        if len(state.tiles) == 0:
            print('perform_simulation called with empty tiles')
            return ALL_TILES_USED, simulation_root_state, solution_tiles_order
        val = self.val
        while True:
            val += 1
            if len(state.tiles) == 0:
                print('solution found in simulation')
                return ALL_TILES_USED, simulation_root_state, solution_tiles_order
            valid_moves = SolutionChecker.get_valid_next_moves(state, state.tiles, val=val, colorful_states=self.colorful_states)
            if not valid_moves:
                return depth, simulation_root_state, solution_tiles_order

            next_random_tile_index = random.randint(0, len(valid_moves) -1)
            success, new_board = SolutionChecker.get_next_turn(
                state, valid_moves[next_random_tile_index], val, destroy_state=True, 
                colorful_states=self.colorful_states
            )
            self.n_tiles_placed += 1
            solution_tiles_order.append(valid_moves[next_random_tile_index])

            if success == ALL_TILES_USED:
                print('grid is full')
                # no LFB on grid; probably means grid is full
                solution_tiles_order.append(valid_moves[next_random_tile_index])
                return ALL_TILES_USED, simulation_root_state, solution_tiles_order
            elif success == NO_NEXT_POSITION_TILES_UNUSED:
                print('no next position with unused tiles')
                return depth, simulation_root_state, solution_tiles_order
            elif success == TILE_CANNOT_BE_PLACED:
                # cannot place the tile. return depth reached
                return depth, simulation_root_state, solution_tiles_order
            else:
                new_tiles = SolutionChecker.eliminate_pair_tiles(state.tiles, valid_moves[next_random_tile_index])
                new_state = State(board=new_board, tiles=new_tiles, parent=state)

                new_state.score = -1  #  because no choice is performed for sequent actions
                state.children.append(new_state)
                state = new_state
            depth += 1
        return depth, simulation_root_state, solution_tiles_order
Beispiel #4
0
    def test_get_next_turn(self):

        success, new_board,  = SolutionChecker.get_next_turn(
            self.state, self.tile, val=1, get_only_success=False, destroy_state=False
        )

        self.assertEqual(success, True)
        np.testing.assert_array_equal(
            new_board,
            np.array([
                [1, 1, 1, 1],
                [1, 1, 1, 1],
                [0, 0, 0, 1]
            ])
        )
        # assert board is not destroyed
        np.testing.assert_array_equal(
            self.state.board,
            np.array([
                [1, 1, 1, 1],
                [1, 1, 1, 0],
                [0, 0, 0, 0]
            ])
        )
Beispiel #5
0
    def predict(self, temp=1, N=3000):
        initial_state = self.state
        state = self.state
        available_tiles = state.tiles
        prev_state = state
        solution_found = False

        depth = 0
        self.val = 1
        while len(state.tiles):
            tile_placed = False
            states = []
            print(len(state.tiles))
            best_score = 0
            for i, tile in enumerate(state.tiles):
                success, new_board = SolutionChecker.get_next_turn(state, tile, self.val, destroy_state=False)
                self.n_tiles_placed += 1

                if success == ALL_TILES_USED:
                    print('solution found!')
                    solution_found = True
                    return initial_state, depth, solution_found
                if success == TILE_CANNOT_BE_PLACED:
                    # cannot place the tile.  this branch will not be considered
                    states.append(None)
                    continue
                else:
                    tile_placed = True
                    new_tiles = SolutionChecker.eliminate_pair_tiles(state.tiles, tile)
                    new_state = State(
                        board=new_board, tiles=new_tiles, parent=state)
                    state.children.append(new_state)
                    simulation_result, solution_tiles_order = self.perform_simulations(new_state, N=N, record_simulations=False)
                    if simulation_result == ALL_TILES_USED:
                        print('solution found in simulation!')
                        print(tile)
                        solution_found = True

                        # update scores of states found in simulation
                        new_state.score = len(state.tiles) / ORIENTATIONS - 1
                        _state = new_state.children[0]
                        while _state.children:
                            _state.score = (len(_state.tiles) / ORIENTATIONS) - 1
                            _state = _state.children[0]

                        if state.tile_placed:
                            self.solution_tiles_order.extend([state.tile_placed] + [tile] + solution_tiles_order)
                        else:
                            self.solution_tiles_order.extend([tile] + solution_tiles_order)
                        return initial_state, depth, solution_found
                    new_state.score = simulation_result
                    if new_state.score > best_score:
                        best_tile = tile
                        best_score = new_state.score
                    new_state.tile_placed = tile
                    state.solution_tiles_order.append(tile)
                    states.append(new_state)
            if not tile_placed:
                # no tile was placed, it's a dead end; end game
                return initial_state, depth, solution_found

            # PERFORMANCE:
            # for visualization this can be changed
            # all tiles will be 1 inside the frame for performance reasons
            self.val += 1

            depth += 1
            best_action = get_max_index(states) 
            prev_state = state
            new_state = states[best_action]
            print(best_tile, prev_state.tile_placed)
            if prev_state.tile_placed:
                self.solution_tiles_order.append(prev_state.tile_placed)


            state = new_state

        print('Solution found!')
        solution_found = True
        return initial_state, depth, solution_found