示例#1
0
def common_generate_logic(args, permalink):
    from randovania.generator import generator

    def status_update(s):
        if args.status_update:
            print(s)

    if permalink.parameters.spoiler:
        debug.set_level(args.debug)

    extra_args = {}
    if args.no_retry:
        extra_args["attempts"] = 0

    before = time.perf_counter()
    layout_description = asyncio.run(
        generator.generate_and_validate_description(
            generator_params=permalink.parameters,
            status_update=status_update,
            validate_after_generation=args.validate,
            timeout=None,
            **extra_args))
    after = time.perf_counter()
    print("Took {} seconds. Hash: {}".format(
        after - before, layout_description.shareable_hash))
    layout_description.save_to_file(args.output_file)
示例#2
0
def distribute_command_logic(args):
    def status_update(s):
        if args.status_update:
            print(s)

    if args.permalink is not None:
        permalink = Permalink.from_str(args.permalink)
    else:
        permalink = asyncio.run(_create_permalink(args))
        print(f"Permalink: {permalink.as_base64_str}")

    if permalink.spoiler:
        debug.set_level(args.debug)

    extra_args = {}
    if args.no_retry:
        extra_args["attempts"] = 0

    before = time.perf_counter()
    layout_description = generator.generate_description(
        permalink=permalink,
        status_update=status_update,
        validate_after_generation=args.validate,
        timeout=None,
        **extra_args)
    after = time.perf_counter()
    print("Took {} seconds. Hash: {}".format(
        after - before, layout_description.shareable_hash))

    layout_description.save_to_file(args.output_file)
示例#3
0
def validate_command_logic(args):
    debug.set_level(args.debug)

    description = LayoutDescription.from_file(args.layout_file)
    if description.player_count != 1:
        raise ValueError(
            f"Validator does not support layouts with more than 1 player.")

    configuration = description.get_preset(0).configuration
    patches = description.all_patches[0]
    total_times = []

    final_state_by_resolve = None
    for _ in range(args.repeat):
        before = time.perf_counter()
        final_state_by_resolve = asyncio.run(
            resolver.resolve(configuration=configuration, patches=patches))
        after = time.perf_counter()
        total_times.append(after - before)
        print("Took {:.3f} seconds. Game is {}.".format(
            total_times[-1], "possible"
            if final_state_by_resolve is not None else "impossible"))
    if args.repeat > 1:
        cli_lib.print_report_multiple_times(total_times)

    if args.repeat < 1:
        raise ValueError("Expected at least 1 repeat")
    return 0 if final_state_by_resolve is not None else 1
示例#4
0
    def __init__(self, options: Options, preset_manager: PresetManager, preview: bool):
        super().__init__()
        self.setupUi(self)
        self.setWindowTitle("Randovania {}".format(VERSION))
        self.is_preview_mode = preview
        self.setAcceptDrops(True)
        common_qt_lib.set_default_window_icon(self)

        self.intro_label.setText(self.intro_label.text().format(version=VERSION))

        self._preset_manager = preset_manager

        if preview:
            debug.set_level(2)

        # Signals
        self.newer_version_signal.connect(self.display_new_version)
        self.background_tasks_button_lock_signal.connect(self.enable_buttons_with_background_tasks)
        self.progress_update_signal.connect(self.update_progress)
        self.stop_background_process_button.clicked.connect(self.stop_background_process)
        self.options_changed_signal.connect(self.on_options_changed)

        self.intro_play_now_button.clicked.connect(lambda: self.welcome_tab_widget.setCurrentWidget(self.tab_play))
        self.open_faq_button.clicked.connect(self._open_faq)
        self.open_database_viewer_button.clicked.connect(self._open_data_visualizer)

        self.import_permalink_button.clicked.connect(self._import_permalink)
        self.create_new_seed_button.clicked.connect(
            lambda: self.welcome_tab_widget.setCurrentWidget(self.tab_create_seed))

        # Menu Bar
        self.menu_action_data_visualizer.triggered.connect(self._open_data_visualizer)
        self.menu_action_item_tracker.triggered.connect(self._open_item_tracker)
        self.menu_action_edit_new_database.triggered.connect(self._open_data_editor_default)
        self.menu_action_edit_existing_database.triggered.connect(self._open_data_editor_prompt)
        self.menu_action_validate_seed_after.triggered.connect(self._on_validate_seed_change)
        self.menu_action_timeout_generation_after_a_time_limit.triggered.connect(self._on_generate_time_limit_change)

        self.generate_seed_tab = GenerateSeedTab(self, self, self, options)
        self.generate_seed_tab.setup_ui()
        self._details_window = SeedDetailsWindow(self, self, options)
        self._details_window.added_to_tab = False

        # Needs the GenerateSeedTab
        self._create_open_map_tracker_actions()

        # Setting this event only now, so all options changed trigger only once
        options.on_options_changed = self.options_changed_signal.emit
        self._options = options
        with options:
            self.on_options_changed()

        self.main_tab_widget.setCurrentIndex(0)

        # Update hints text
        self._update_hints_text()
示例#5
0
def _generate_layout_worker(output_pipe: Connection,
                            debug_level: int,
                            extra_args: dict):
    def status_update(message: str):
        output_pipe.send(message)
        if output_pipe.poll():
            raise RuntimeError(output_pipe.recv())

    debug.set_level(debug_level)
    return asyncio.run(generator.generate_and_validate_description(status_update=status_update, **extra_args))
示例#6
0
def validate_command_logic(args):
    debug.set_level(args.debug)
    data = prime_database.decode_data_file(args)
    game = data_reader.decode_data(data)

    description = LayoutDescription.from_file(args.layout_file)
    configuration = description.permalink.layout_configuration
    patches = description.patches

    final_state_by_resolve = resolver.resolve(configuration=configuration,
                                              game=game,
                                              patches=patches)
    print(final_state_by_resolve)
示例#7
0
async def test_resolver_with_log_file(test_files_dir, seed_name: str):
    # Setup
    debug.set_level(2)

    description = LayoutDescription.from_file(test_files_dir.joinpath("log_files", seed_name))
    configuration = description.permalink.presets[0].configuration
    patches = description.all_patches[0]

    # Run
    final_state_by_resolve = await resolver.resolve(configuration=configuration,
                                                    patches=patches)

    # Assert
    assert final_state_by_resolve is not None
示例#8
0
def test_resolver_with_log_file(test_files_dir):
    # Setup
    debug.set_level(0)

    description = LayoutDescription.from_file(test_files_dir.joinpath("log_files", "seed_a.json"))
    configuration = description.permalink.presets[0].layout_configuration
    patches = description.all_patches[0]

    # Run
    final_state_by_resolve = resolver.resolve(configuration=configuration,
                                              patches=patches)

    # Assert
    assert final_state_by_resolve is not None
示例#9
0
def distribute_command_logic(args):
    from randovania.layout.permalink import Permalink
    from randovania.generator import generator

    async def _create_permalink(args_) -> Permalink:
        from randovania.interface_common import persistence
        from randovania.interface_common.preset_manager import PresetManager

        preset_manager = PresetManager(persistence.user_data_dir())
        await preset_manager.load_user_presets()
        preset = preset_manager.preset_for_name(args_.preset_name).get_preset()

        return Permalink(
            args_.seed_number,
            spoiler=True,
            presets={i: preset
                     for i in range(args_.player_count)},
        )

    def status_update(s):
        if args.status_update:
            print(s)

    if args.permalink is not None:
        permalink = Permalink.from_str(args.permalink)
    else:
        permalink = asyncio.run(_create_permalink(args))
        print(f"Permalink: {permalink.as_base64_str}")

    if permalink.spoiler:
        debug.set_level(args.debug)

    extra_args = {}
    if args.no_retry:
        extra_args["attempts"] = 0

    before = time.perf_counter()
    layout_description = generator.generate_description(
        permalink=permalink,
        status_update=status_update,
        validate_after_generation=args.validate,
        timeout=None,
        **extra_args)
    after = time.perf_counter()
    print("Took {} seconds. Hash: {}".format(
        after - before, layout_description.shareable_hash))

    layout_description.save_to_file(args.output_file)
示例#10
0
def validate_command_logic(args):
    debug.set_level(args.debug)

    description = LayoutDescription.from_file(args.layout_file)

    if description.permalink.player_count != 1:
        raise ValueError(f"Validator does not support layouts with more than 1 player.")

    configuration = description.permalink.presets[0].layout_configuration
    patches = description.all_patches[0]

    final_state_by_resolve = resolver.resolve(
        configuration=configuration,
        patches=patches
    )
    print(final_state_by_resolve)
示例#11
0
def test_resolver_with_log_file(test_files_dir):
    # Setup
    debug.set_level(0)

    description = LayoutDescription.from_file(
        test_files_dir.joinpath("log_files", "seed_a.json"))
    configuration = description.permalink.layout_configuration
    game = data_reader.decode_data(configuration.game_data)
    patches = description.patches

    # Run
    final_state_by_resolve = resolver.resolve(configuration=configuration,
                                              game=game,
                                              patches=patches)

    # Assert
    assert final_state_by_resolve is not None
示例#12
0
def test_compare_generated_with_data(mock_permalink_as_str: PropertyMock,
                                     layout_description: LayoutDescription):
    debug.set_level(0)
    status_update = MagicMock()
    mock_permalink_as_str.return_value = "fixed-seed!"

    generated_description = generator.generate_description(
        layout_description.permalink,
        status_update=status_update,
        validate_after_generation=True,
        timeout=None)

    # indices: List[int] = [None] * echoes_pickup_database.total_pickup_count
    # for index, pickup in generated_description.patches.pickup_assignment.items():
    #     indices[index.index] = echoes_pickup_database.original_index(pickup).index
    # print(indices)

    assert generated_description.without_solver_path == layout_description
示例#13
0
def distribute_command_logic(args):
    def status_update(s):
        pass

    permalink = Permalink.from_str(args.permalink)
    if permalink.spoiler:
        debug.set_level(args.debug)

    before = time.perf_counter()
    layout_description = generator.generate_description(
        permalink=permalink,
        status_update=status_update,
        validate_after_generation=args.validate,
        timeout=None)
    after = time.perf_counter()
    print("Took {} seconds. Hash: {}".format(
        after - before, layout_description.shareable_hash))

    layout_description.save_to_file(args.output_file)
示例#14
0
def validate_command_logic(args):
    debug.set_level(args.debug)

    description = LayoutDescription.from_file(args.layout_file)
    if description.player_count != 1:
        raise ValueError(
            f"Validator does not support layouts with more than 1 player.")

    configuration = description.get_preset(0).configuration
    patches = description.all_patches[0]

    before = time.perf_counter()
    final_state_by_resolve = asyncio.run(
        resolver.resolve(configuration=configuration, patches=patches))
    after = time.perf_counter()
    print("Took {} seconds. Game is {}.".format(
        after - before,
        "possible" if final_state_by_resolve is not None else "impossible"))
    return 0 if final_state_by_resolve is not None else 1
示例#15
0
def _generate_layout_worker(output_pipe: Connection,
                            permalink: Permalink,
                            validate_after_generation: bool,
                            timeout_during_generation: bool,
                            debug_level: int):
    def status_update(message: str):
        output_pipe.send(message)
        if output_pipe.poll():
            raise RuntimeError(output_pipe.recv())

    debug.set_level(debug_level)
    extra_args = {}
    if not timeout_during_generation:
        extra_args["timeout"] = None

    return generator.generate_description(permalink,
                                          status_update=status_update,
                                          validate_after_generation=validate_after_generation,
                                          **extra_args)
示例#16
0
def _generate_layout_worker(output_pipe, permalink: Permalink,
                            validate_after_generation: bool,
                            timeout_during_generation: bool, debug_level: int):
    try:

        def status_update(message: str):
            output_pipe.send(message)

        debug.set_level(debug_level)
        extra_args = {}
        if not timeout_during_generation:
            extra_args["timeout"] = None

        layout_description = generator.generate_description(
            permalink,
            status_update=status_update,
            validate_after_generation=validate_after_generation,
            **extra_args)
        output_pipe.send(layout_description)
    except Exception as e:
        traceback.print_exc()
        output_pipe.send(e)
示例#17
0
def common_generate_logic(args, permalink):
    from randovania.generator import generator

    def status_update(s):
        if args.status_update:
            print(s)

    if permalink.parameters.spoiler:
        debug.set_level(args.debug)

    extra_args = {}
    if args.no_retry:
        extra_args["attempts"] = 0

    shareable_hashes = []
    total_times = []

    layout_description = None
    for _ in range(args.repeat):
        before = time.perf_counter()
        layout_description = asyncio.run(
            generator.generate_and_validate_description(
                generator_params=permalink.parameters,
                status_update=status_update,
                validate_after_generation=args.validate,
                timeout=None,
                **extra_args))
        after = time.perf_counter()
        total_times.append(after - before)
        shareable_hashes.append(layout_description.shareable_hash)
        print("Took {:.3f} seconds. Hash: {}".format(total_times[-1],
                                                     shareable_hashes[-1]))

    assert layout_description is not None
    layout_description.save_to_file(args.output_file)
    if args.repeat > 1:
        cli_lib.print_report_multiple_times(total_times)
示例#18
0
def distribute_command_logic(args):
    debug.set_level(args.debug)

    def status_update(s):
        pass

    permalink = Permalink.from_str(args.permalink)

    before = time.perf_counter()
    layout_description = generator.generate_description(
        permalink=permalink,
        status_update=status_update,
        validate_after_generation=args.validate,
        timeout=None)
    after = time.perf_counter()
    print("Took {} seconds. Hash: {}".format(
        after - before, layout_description.shareable_hash))

    layout_description.save_to_file(args.output_file)
    simplified_patcher.write_patcher_file_to_disk(
        args.output_file.with_suffix(".patcher-json"),
        layout_description,
        CosmeticPatches.default(),
    )
示例#19
0
    def __init__(self, options: Options, preset_manager: PresetManager,
                 network_client, preview: bool):
        super().__init__()
        self.setupUi(self)
        self.setWindowTitle("Randovania {}".format(VERSION))
        self._is_preview_mode = preview
        self.setAcceptDrops(True)
        common_qt_lib.set_default_window_icon(self)

        self.setup_about_text()
        self.setup_welcome_text()
        self.browse_racetime_label.setText(
            self.browse_racetime_label.text().replace("color:#0000ff;", ""))

        self._preset_manager = preset_manager
        self.network_client = network_client

        if preview:
            debug.set_level(2)

        if randovania.is_frozen():
            self.menu_bar.removeAction(self.menu_edit.menuAction())

        # Signals
        self.options_changed_signal.connect(self.on_options_changed)
        self.GameDetailsSignal.connect(self._open_game_details)
        self.InitPostShowSignal.connect(self.initialize_post_show)

        self.intro_play_now_button.clicked.connect(
            lambda: self.main_tab_widget.setCurrentWidget(self.tab_play))
        self.open_faq_button.clicked.connect(self._open_faq)
        self.open_database_viewer_button.clicked.connect(
            partial(self._open_data_visualizer_for_game,
                    RandovaniaGame.METROID_PRIME_ECHOES))

        self.import_permalink_button.clicked.connect(self._import_permalink)
        self.import_game_file_button.clicked.connect(self._import_spoiler_log)
        self.browse_racetime_button.clicked.connect(self._browse_racetime)
        self.create_new_seed_button.clicked.connect(
            lambda: self.main_tab_widget.setCurrentWidget(self.tab_create_seed
                                                          ))

        # Menu Bar
        self.game_menus = []
        self.menu_action_edits = []

        for game in RandovaniaGame.sorted_all_games():
            # Sub-Menu in Open Menu
            game_menu = QtWidgets.QMenu(self.menu_open)
            game_menu.setTitle(_t(game.long_name))
            game_menu.game = game

            if game.data.development_state.can_view(False):
                self.menu_open.addAction(game_menu.menuAction())
            self.game_menus.append(game_menu)

            game_trick_details_menu = QtWidgets.QMenu(game_menu)
            game_trick_details_menu.setTitle(_t("Trick Details"))
            self._setup_trick_difficulties_menu_on_show(
                game_trick_details_menu, game)

            game_data_visualizer_action = QtGui.QAction(game_menu)
            game_data_visualizer_action.setText(_t("Data Visualizer"))
            game_data_visualizer_action.triggered.connect(
                partial(self._open_data_visualizer_for_game, game))

            game_menu.addAction(game_trick_details_menu.menuAction())
            game_menu.addAction(game_data_visualizer_action)

            # Data Editor
            action = QtGui.QAction(self)
            action.setText(_t(game.long_name))
            self.menu_internal.addAction(action)
            action.triggered.connect(
                partial(self._open_data_editor_for_game, game))
            self.menu_action_edits.append(action)

        self.menu_action_edit_existing_database.triggered.connect(
            self._open_data_editor_prompt)
        self.menu_action_validate_seed_after.triggered.connect(
            self._on_validate_seed_change)
        self.menu_action_timeout_generation_after_a_time_limit.triggered.connect(
            self._on_generate_time_limit_change)
        self.menu_action_dark_mode.triggered.connect(
            self._on_menu_action_dark_mode)
        self.menu_action_experimental_games.triggered.connect(
            self._on_menu_action_experimental_games)
        self.menu_action_open_auto_tracker.triggered.connect(
            self._open_auto_tracker)
        self.menu_action_previously_generated_games.triggered.connect(
            self._on_menu_action_previously_generated_games)
        self.menu_action_log_files_directory.triggered.connect(
            self._on_menu_action_log_files_directory)
        self.menu_action_layout_editor.triggered.connect(
            self._on_menu_action_layout_editor)

        # Setting this event only now, so all options changed trigger only once
        options.on_options_changed = self.options_changed_signal.emit
        self._options = options

        self.main_tab_widget.setCurrentIndex(0)
示例#20
0
    def __init__(self, options: Options, preset_manager: PresetManager,
                 network_client: QtNetworkClient, preview: bool):
        super().__init__()
        self.setupUi(self)
        self.setWindowTitle("Randovania {}".format(VERSION))
        self._is_preview_mode = preview
        self.setAcceptDrops(True)
        common_qt_lib.set_default_window_icon(self)

        # Remove all hardcoded link color
        about_document: QtGui.QTextDocument = self.about_text_browser.document(
        )
        about_document.setHtml(about_document.toHtml().replace(
            "color:#0000ff;", ""))
        self.browse_racetime_label.setText(
            self.browse_racetime_label.text().replace("color:#0000ff;", ""))

        self.intro_label.setText(
            self.intro_label.text().format(version=VERSION))

        self._preset_manager = preset_manager
        self.network_client = network_client

        if preview:
            debug.set_level(2)

        # Signals
        self.newer_version_signal.connect(self.display_new_version)
        self.options_changed_signal.connect(self.on_options_changed)
        self.GameDetailsSignal.connect(self._open_game_details)

        self.intro_play_now_button.clicked.connect(
            lambda: self.welcome_tab_widget.setCurrentWidget(self.tab_play))
        self.open_faq_button.clicked.connect(self._open_faq)
        self.open_database_viewer_button.clicked.connect(
            partial(self._open_data_visualizer_for_game,
                    RandovaniaGame.PRIME2))

        self.import_permalink_button.clicked.connect(self._import_permalink)
        self.import_game_file_button.clicked.connect(self._import_spoiler_log)
        self.browse_racetime_button.clicked.connect(self._browse_racetime)
        self.browse_sessions_button.clicked.connect(
            self._browse_for_game_session)
        self.host_new_game_button.clicked.connect(self._host_game_session)
        self.create_new_seed_button.clicked.connect(
            lambda: self.welcome_tab_widget.setCurrentWidget(self.
                                                             tab_create_seed))

        # Menu Bar
        for action, game in ((self.menu_action_visualize_prime_1,
                              RandovaniaGame.PRIME1),
                             (self.menu_action_visualize_prime_2,
                              RandovaniaGame.PRIME2),
                             (self.menu_action_visualize_prime_3,
                              RandovaniaGame.PRIME3)):
            action.triggered.connect(
                partial(self._open_data_visualizer_for_game, game))

        for action, game in ((self.menu_action_edit_prime_1,
                              RandovaniaGame.PRIME1),
                             (self.menu_action_edit_prime_2,
                              RandovaniaGame.PRIME2),
                             (self.menu_action_edit_prime_3,
                              RandovaniaGame.PRIME3)):
            action.triggered.connect(
                partial(self._open_data_editor_for_game, game))

        self.menu_action_item_tracker.triggered.connect(
            self._open_item_tracker)
        self.menu_action_map_tracker.triggered.connect(
            self._on_menu_action_map_tracker)
        self.menu_action_edit_existing_database.triggered.connect(
            self._open_data_editor_prompt)
        self.menu_action_validate_seed_after.triggered.connect(
            self._on_validate_seed_change)
        self.menu_action_timeout_generation_after_a_time_limit.triggered.connect(
            self._on_generate_time_limit_change)
        self.menu_action_dark_mode.triggered.connect(
            self._on_menu_action_dark_mode)
        self.menu_action_open_auto_tracker.triggered.connect(
            self._open_auto_tracker)
        self.menu_action_previously_generated_games.triggered.connect(
            self._on_menu_action_previously_generated_games)
        self.menu_action_layout_editor.triggered.connect(
            self._on_menu_action_layout_editor)
        self.action_login_window.triggered.connect(self._action_login_window)

        self.generate_seed_tab = GenerateSeedTab(self, self, options)
        self.generate_seed_tab.setup_ui()

        # Needs the GenerateSeedTab
        self._setup_difficulties_menu()

        # Setting this event only now, so all options changed trigger only once
        options.on_options_changed = self.options_changed_signal.emit
        self._options = options
        with options:
            self.on_options_changed()

        self.main_tab_widget.setCurrentIndex(0)

        # Update hints text
        self._update_hints_text()
示例#21
0
    def __init__(self, options: Options, preview: bool):
        super().__init__()
        self.setupUi(self)
        self.setWindowTitle("Randovania {}".format(VERSION))
        self.is_preview_mode = preview
        self.setAcceptDrops(True)
        set_default_window_icon(self)

        self.intro_label.setText(
            self.intro_label.text().format(version=VERSION))

        if preview:
            debug.set_level(2)

        # Signals
        self.newer_version_signal.connect(self.display_new_version)
        self.background_tasks_button_lock_signal.connect(
            self.enable_buttons_with_background_tasks)
        self.progress_update_signal.connect(self.update_progress)
        self.stop_background_process_button.clicked.connect(
            self.stop_background_process)
        self.options_changed_signal.connect(self.on_options_changed)

        # Menu Bar
        self.menu_action_data_visualizer.triggered.connect(
            self._open_data_visualizer)
        self.menu_action_existing_seed_details.triggered.connect(
            self._open_existing_seed_details)
        self.menu_action_tracker.triggered.connect(self._open_tracker)
        self.menu_action_edit_new_database.triggered.connect(
            self._open_data_editor_default)
        self.menu_action_edit_existing_database.triggered.connect(
            self._open_data_editor_prompt)
        self.menu_action_export_iso.triggered.connect(self._export_iso)
        self.menu_action_validate_seed_after.triggered.connect(
            self._on_validate_seed_change)
        self.menu_action_timeout_generation_after_a_time_limit.triggered.connect(
            self._on_generate_time_limit_change)

        self.menu_action_export_iso.setEnabled(False)

        _translate = QtCore.QCoreApplication.translate
        self.tabs = []

        from randovania.gui.game_patches_window import GamePatchesWindow
        from randovania.gui.iso_management_window import ISOManagementWindow
        from randovania.gui.logic_settings_window import LogicSettingsWindow
        from randovania.gui.cosmetic_window import CosmeticWindow
        from randovania.gui.main_rules import MainRulesWindow

        self.tab_windows = [
            (ISOManagementWindow, "ROM Settings"),
            (GamePatchesWindow, "Game Patches"),
            (MainRulesWindow, "Main Rules"),
            (LogicSettingsWindow, "Logic Settings"),
            (CosmeticWindow, "Cosmetic"),
        ]

        for i, tab in enumerate(self.tab_windows):
            self.windows.append(tab[0](self, self, options))
            self.tabs.append(self.windows[i].centralWidget)
            self.tabWidget.insertTab(i + 1, self.tabs[i],
                                     _translate("MainWindow", tab[1]))

        # Setting this event only now, so all options changed trigger only once
        options.on_options_changed = self.options_changed_signal.emit
        self._options = options
        with options:
            self.on_options_changed()

        self.tabWidget.setCurrentIndex(0)

        # Update hints text
        self._update_hints_text()