示例#1
0
    async def on_database_area_selected(self, ctx: ComponentContext,
                                        game: RandovaniaGame,
                                        split_world: SplitWorld,
                                        world_id: int):
        option_selected = ctx.selected_options[0]

        valid_items = [
            area for i, area in enumerate(split_world.areas)
            if f"area_{i}" == option_selected
        ]
        if not valid_items:
            return await ctx.edit_origin(
                components=[],
                embeds=[],
                content=
                f"Invalid selected option, unable to find given area '{option_selected}'."
            )

        area = valid_items[0]
        db = default_database.game_description_for(game)

        title = "{}: {}".format(game.long_name, db.world_list.area_name(area))
        valid_nodes = [
            node for node in sorted(area.nodes, key=lambda it: it.name)
            if not node.is_derived_node
        ]

        select = manage_components.create_select(
            options=[
                manage_components.create_select_option(node.name,
                                                       value=node.name)
                for node in valid_nodes
            ],
            max_values=min(10, len(valid_nodes)),
            custom_id=f"{game.value}_world_{world_id}_{option_selected}",
            placeholder="Choose the room",
        )
        action_row = manage_components.create_actionrow(select)

        files = []

        area_image = render_area_with_pillow(area, game.data_path)
        if area_image is not None:
            files.append(
                discord.File(area_image, filename=f"{area.name}_image.png"))

        area_graph = render_area_with_graphviz(area)
        if area_graph is not None:
            files.append(
                discord.File(area_graph, filename=f"{area.name}_graph.png"))

        logging.info("Responding to area for %s with %d attachments.",
                     area.name, len(files))
        await ctx.send(
            content=f"**{title}**\nRequested by {ctx.author.display_name}.",
            files=files,
            components=[
                action_row,
            ],
        )
示例#2
0
    def valid_targets(self) -> List[AreaIdentifier]:
        if self.mode == TeleporterShuffleMode.ONE_WAY_ANYTHING:
            return [
                location
                for location in self.excluded_targets.areas_list(self.game)
                if location not in self.excluded_targets.locations
            ]

        elif self.mode in {
                TeleporterShuffleMode.ONE_WAY_ELEVATOR,
                TeleporterShuffleMode.ONE_WAY_ELEVATOR_REPLACEMENT
        }:
            world_list = default_database.game_description_for(
                self.game).world_list
            result = []
            for identifier in self.editable_teleporters:
                node = world_list.node_by_identifier(identifier)
                if isinstance(node, TeleporterNode) and node.editable:
                    # Valid destinations must be valid starting areas
                    area = world_list.nodes_to_area(node)
                    if area.valid_starting_location:
                        result.append(identifier.area_identifier)
                    # Hack for Metroid Prime 1, where the scripting for Metroid Prime Lair is dependent on the previous room
                    elif area.name == "Metroid Prime Lair":
                        result.append(
                            AreaIdentifier.from_string(
                                "Impact Crater/Subchamber Five"))
            return result
        else:
            return []
示例#3
0
    def update_content(self, configuration: BaseConfiguration,
                       all_patches: dict[int, GamePatches],
                       players: PlayersConfiguration):
        self.tree_widget.clear()
        self.tree_widget.setColumnCount(2)
        self.tree_widget.setHeaderLabels(["Source", "Destination"])

        world_list = default_database.game_description_for(
            self.game_enum).world_list
        patches = all_patches[players.player_index]

        per_world: dict[str, dict[str, str]] = collections.defaultdict(dict)

        for source_loc, destination_loc in patches.elevator_connection.items():
            source_world = world_list.world_by_area_location(
                source_loc.area_identifier)
            source_name = elevators.get_elevator_or_area_name(
                self.game_enum, world_list, source_loc.area_identifier, True)

            per_world[source_world.
                      name][source_name] = elevators.get_elevator_or_area_name(
                          self.game_enum, world_list, destination_loc, True)

        for world_name, world_contents in iterate_key_sorted(per_world):
            world_item = QtWidgets.QTreeWidgetItem(self.tree_widget)
            world_item.setText(0, world_name)
            world_item.setExpanded(True)
            for source_name, destination in iterate_key_sorted(world_contents):
                area_item = QtWidgets.QTreeWidgetItem(world_item)
                area_item.setText(0, source_name)
                area_item.setText(1, destination)

        self.tree_widget.resizeColumnToContents(0)
        self.tree_widget.resizeColumnToContents(1)
示例#4
0
def prime2_preset_tabs(editor: PresetEditor, window_manager: WindowManager):
    game_enum = editor.game
    game_description = default_database.game_description_for(game_enum)

    from randovania.gui.preset_settings.trick_level_tab import PresetTrickLevel
    from randovania.gui.preset_settings.patcher_energy_tab import PresetPatcherEnergy
    from randovania.gui.preset_settings.elevators_tab import PresetElevators
    from randovania.gui.preset_settings.starting_area_tab import PresetMetroidStartingArea
    from randovania.gui.preset_settings.generation_tab import PresetGeneration
    from randovania.games.prime2.gui.preset_settings.echoes_goal_tab import PresetEchoesGoal
    from randovania.games.prime2.gui.preset_settings.echoes_hints_tab import PresetEchoesHints
    from randovania.games.prime2.gui.preset_settings.echoes_translators_tab import PresetEchoesTranslators
    from randovania.games.prime2.gui.preset_settings.echoes_beam_configuration_tab import PresetEchoesBeamConfiguration
    from randovania.games.prime2.gui.preset_settings.echoes_patches_tab import PresetEchoesPatches
    from randovania.gui.preset_settings.location_pool_tab import PresetLocationPool
    from randovania.games.prime2.gui.preset_settings.echoes_item_pool_tab import EchoesPresetItemPool
    return [
        PresetTrickLevel(editor, game_description, window_manager),
        PresetPatcherEnergy(editor, game_enum),
        PresetElevators(editor, game_description),
        PresetMetroidStartingArea(editor, game_description),
        PresetGeneration(editor, game_description),
        PresetEchoesGoal(editor),
        PresetEchoesHints(editor),
        PresetEchoesTranslators(editor),
        PresetEchoesBeamConfiguration(editor),
        PresetEchoesPatches(editor),
        PresetLocationPool(editor, game_description),
        EchoesPresetItemPool(editor),
    ]
示例#5
0
def prime1_preset_tabs(editor: PresetEditor, window_manager: WindowManager):
    game_enum = editor.game
    game_description = default_database.game_description_for(game_enum)

    from randovania.gui.preset_settings.trick_level_tab import PresetTrickLevel
    from randovania.gui.preset_settings.patcher_energy_tab import PresetPatcherEnergy
    from randovania.gui.preset_settings.elevators_tab import PresetElevators
    from randovania.gui.preset_settings.starting_area_tab import PresetMetroidStartingArea
    from randovania.games.prime1.gui.preset_settings.prime_goal_tab import PresetPrimeGoal
    from randovania.games.prime1.gui.preset_settings.prime_hints_tab import PresetPrimeHints
    from randovania.games.prime1.gui.preset_settings.prime_patches_tab import PresetPrimePatches
    from randovania.gui.preset_settings.location_pool_tab import PresetLocationPool
    from randovania.gui.preset_settings.metroid_item_pool_tab import MetroidPresetItemPool
    from randovania.games.prime1.gui.preset_settings.prime_generation_tab import PresetPrimeGeneration
    return [
        PresetTrickLevel(editor, game_description, window_manager),
        PresetPatcherEnergy(editor, game_enum),
        PresetElevators(editor, game_description),
        PresetMetroidStartingArea(editor, game_description),
        PresetPrimeGeneration(editor, game_description),
        PresetPrimeGoal(editor),
        PresetPrimeHints(editor),
        PresetPrimePatches(editor),
        PresetLocationPool(editor, game_description),
        MetroidPresetItemPool(editor),
    ]
示例#6
0
    async def _show_dialog_for_prime3_layout(self):
        from randovania.games.patchers import gollop_corruption_patcher

        patches = self.layout_description.all_patches[
            self.current_player_index]
        game = default_database.game_description_for(RandovaniaGame.PRIME3)

        item_names = []
        for index in range(game.world_list.num_pickup_nodes):
            p_index = PickupIndex(index)
            if p_index in patches.pickup_assignment:
                name = patches.pickup_assignment[p_index].pickup.name
            else:
                name = "Missile Expansion"
            item_names.append(name)

        layout_string = gollop_corruption_patcher.layout_string_for_items(
            item_names)
        starting_location = patches.starting_location

        commands = "\n".join([
            f'set seed="{layout_string}"',
            f'set "starting_items={gollop_corruption_patcher.starting_items_for(patches.starting_items)}"',
            f'set "starting_location={gollop_corruption_patcher.starting_location_for(starting_location)}"',
        ])
        message_box = QtWidgets.QMessageBox(QtWidgets.QMessageBox.Information,
                                            "Commands for patcher", commands)
        common_qt_lib.set_default_window_icon(message_box)
        message_box.setTextInteractionFlags(Qt.TextSelectableByMouse)
        QApplication.clipboard().setText(commands)
        await async_dialog.execute_dialog(message_box)
示例#7
0
    def __init__(self, editor: PresetEditor):
        super().__init__()
        self.setupUi(self)

        self._editor = editor
        size_policy = QSizePolicy(QSizePolicy.Preferred, QSizePolicy.Fixed)
        self.item_pool_layout.setAlignment(Qt.AlignTop)

        # Relevant Items
        self.game = editor.game
        self.game_description = default_database.game_description_for(
            self.game)
        item_database = default_database.item_database_for_game(self.game)

        self._energy_tank_item = item_database.major_items["Energy Tank"]

        self._register_random_starting_events()
        self._create_categories_boxes(item_database, size_policy)
        self._create_customizable_default_items(item_database)
        self._create_progressive_widgets(item_database)
        self._create_major_item_boxes(item_database,
                                      self.game_description.resource_database)
        self._create_energy_tank_box()
        self._create_split_ammo_widgets(item_database)
        self._create_ammo_pickup_boxes(size_policy, item_database)
示例#8
0
 def format_area(self, location: PickupLocation, with_world: bool,
                 with_color: bool) -> str:
     world_list = default_database.game_description_for(
         location.game).world_list
     area = world_list.nodes_to_area(
         world_list.node_from_pickup_index(location.location))
     return area.name
示例#9
0
    def _setup_difficulties_menu(self, game: RandovaniaGame,
                                 menu: QtWidgets.QMenu):
        from randovania.game_description import default_database
        game = default_database.game_description_for(game)
        tricks_in_use = used_tricks(game)

        menu.clear()
        for trick in sorted(game.resource_database.trick,
                            key=lambda _trick: _trick.long_name):
            if trick not in tricks_in_use:
                continue

            trick_menu = QtWidgets.QMenu(self)
            trick_menu.setTitle(trick.long_name)
            menu.addAction(trick_menu.menuAction())

            used_difficulties = difficulties_for_trick(game, trick)
            for i, trick_level in enumerate(iterate_enum(LayoutTrickLevel)):
                if trick_level in used_difficulties:
                    difficulty_action = QtWidgets.QAction(self)
                    difficulty_action.setText(trick_level.long_name)
                    trick_menu.addAction(difficulty_action)
                    difficulty_action.triggered.connect(
                        functools.partial(self._open_trick_details_popup, game,
                                          trick, trick_level))
    def __init__(self):
        super().__init__()
        self.logger.setLevel(logging.DEBUG)
        self.window = QMainWindow()
        self.setupUi(self.window)
        common_qt_lib.set_default_window_icon(self.window)

        self.pickups = []

        self.collect_location_combo.setVisible(False)
        self.setup_collect_location_combo_button = QtWidgets.QPushButton(
            self.window)
        self.setup_collect_location_combo_button.setText(
            "Load list of locations")
        self.setup_collect_location_combo_button.clicked.connect(
            self._setup_locations_combo)
        self.gridLayout.addWidget(self.setup_collect_location_combo_button, 0,
                                  0, 1, 2)

        self.collect_location_button.clicked.connect(self._emit_collection)
        self.collect_location_button.setEnabled(False)
        self.collect_randomly_check.stateChanged.connect(
            self._on_collect_randomly_toggle)
        self._timer = QtCore.QTimer(self.window)
        self._timer.timeout.connect(self._collect_randomly)
        self._timer.setInterval(10000)

        self._used_version = echoes_dol_versions.ALL_VERSIONS[0]
        self._connector = EchoesRemoteConnector(self._used_version)
        self.game = default_database.game_description_for(
            RandovaniaGame.METROID_PRIME_ECHOES)

        self._game_memory = bytearray(24 * (2**20))
        self._game_memory_initialized = False
示例#11
0
def dread_preset_tabs(editor: PresetEditor, window_manager: WindowManager):
    game_enum = editor.game
    game_description = default_database.game_description_for(game_enum)

    from randovania.gui.preset_settings.trick_level_tab import PresetTrickLevel
    from randovania.gui.preset_settings.elevators_tab import PresetElevators
    from randovania.gui.preset_settings.starting_area_tab import PresetMetroidStartingArea
    from randovania.gui.preset_settings.generation_tab import PresetGeneration
    from randovania.gui.preset_settings.location_pool_tab import PresetLocationPool
    from randovania.gui.preset_settings.metroid_item_pool_tab import MetroidPresetItemPool
    from randovania.gui.preset_settings.patcher_energy_tab import PresetPatcherEnergy
    from randovania.games.dread.gui.preset_settings.dread_patches_tab import PresetDreadPatches

    return [
        PresetTrickLevel(editor, game_description, window_manager),
        *([
            PresetElevators(editor, game_description),
            PresetMetroidStartingArea(editor, game_description),
        ] if window_manager.is_preview_mode else []),
        PresetGeneration(editor, game_description),
        PresetLocationPool(editor, game_description),
        MetroidPresetItemPool(editor),
        PresetPatcherEnergy(editor, RandovaniaGame.METROID_DREAD),
        PresetDreadPatches(editor),
    ]
    def _create_energy_box(self):
        category_box, category_layout, _ = self._boxes_for_category["energy_tank"]
        game_description = default_database.game_description_for(self.game)

        row = 0
        for item in [self._energy_tank_item, self._energy_part_item]:
            resource = game_description.resource_database.get_item(item.progression[0])

            starting_label = QtWidgets.QLabel(category_box)
            starting_label.setText(f"Starting {item.name}")
            category_layout.addWidget(starting_label, row, 0)

            spinbox = self._energy_item_to_starting_spinbox[item] = ScrollProtectedSpinBox(category_box)
            spinbox.setMaximum(resource.max_capacity)
            spinbox.valueChanged.connect(functools.partial(self._on_update_starting, item=item))
            category_layout.addWidget(spinbox, row, 1)

            row += 1

            shuffled_label = QtWidgets.QLabel(category_box)
            shuffled_label.setText(f"Shuffled {item.name}")
            category_layout.addWidget(shuffled_label, row, 0)

            spinbox = self._energy_item_to_shuffled_spinbox[item] = ScrollProtectedSpinBox(category_box)
            spinbox.setMaximum(DEFAULT_MAXIMUM_SHUFFLED[-1])
            spinbox.valueChanged.connect(functools.partial(self._on_update_shuffled, item=item))
            category_layout.addWidget(spinbox, row, 1)

            row += 1
示例#13
0
 def as_json(self) -> list:
     world_list = default_database.game_description_for(self.game).world_list
     return list(sorted(
         world_list.area_name(world_list.area_by_area_location(location), separator="/",
                              distinguish_dark_aether=False)
         for location in self.locations
     ))
示例#14
0
def test_starting_location_world_select(skip_qtbot, preset_manager):
    # Setup
    base = preset_manager.default_preset_for_game(
        RandovaniaGame.METROID_PRIME_ECHOES).get_preset()
    preset = dataclasses.replace(
        base,
        uuid=uuid.UUID('b41fde84-1f57-4b79-8cd6-3e5a78077fa6'),
        base_preset_uuid=base.uuid)
    editor = PresetEditor(preset)
    window = PresetMetroidStartingArea(
        editor, default_database.game_description_for(preset.game))
    skip_qtbot.addWidget(window)

    # Run
    checkbox_list = window._starting_location_for_world
    window.on_preset_changed(editor.create_custom_preset_with())
    assert len(checkbox_list) == 10
    temple_grounds_checkbox = checkbox_list["Temple Grounds"]
    assert temple_grounds_checkbox.checkState() == Qt.PartiallyChecked
    skip_qtbot.mouseClick(temple_grounds_checkbox, Qt.LeftButton)
    assert temple_grounds_checkbox.checkState() == Qt.Checked
    assert len(editor.configuration.starting_location.locations) == 39
    skip_qtbot.mouseClick(temple_grounds_checkbox, Qt.LeftButton)
    assert temple_grounds_checkbox.checkState() == Qt.Unchecked
    assert len(editor.configuration.starting_location.locations) == 0
    skip_qtbot.mouseClick(temple_grounds_checkbox, Qt.LeftButton)
    window.on_preset_changed(editor.create_custom_preset_with())
    assert temple_grounds_checkbox.checkState() == Qt.Checked
    assert len(editor.configuration.starting_location.locations) == 39
示例#15
0
def game_description_for_layout(
        configuration: BaseConfiguration) -> GameDescription:
    game = derived_nodes.remove_inactive_layers(
        default_database.game_description_for(configuration.game),
        configuration.active_layers(),
    )

    return game
示例#16
0
 def format_area(self, location: PickupLocation, with_world: bool,
                 with_color: bool) -> str:
     world_list = default_database.game_description_for(
         location.game).world_list
     result = _area_name(
         world_list, world_list.node_from_pickup_index(location.location),
         not with_world)
     return colorize_text(self.color_location, result, with_color)
示例#17
0
 def areas_list(cls, game: RandovaniaGame):
     world_list = default_database.game_description_for(game).world_list
     areas = [
         AreaLocation(world.world_asset_id, area.area_asset_id)
         for world in world_list.worlds for area in world.areas
         if area.valid_starting_location
     ]
     return list(sorted(areas))
def test_find_database_errors(game_enum: RandovaniaGame):
    # Setup
    game = default_database.game_description_for(game_enum)

    # Run
    errors = integrity_check.find_database_errors(game)

    # Assert
    assert errors == []
示例#19
0
def test_logic_bootstrap(preset_manager, game_enum, empty_patches):
    configuration = preset_manager.default_preset_for_game(game_enum).get_preset().configuration
    game = default_database.game_description_for(configuration.game)

    new_game, state = game_enum.generator.bootstrap.logic_bootstrap(
        configuration,
        game.get_mutable(),
        dataclasses.replace(empty_patches, configuration=configuration, starting_location=game.starting_location),
    )
示例#20
0
 def areas_list(cls, game: RandovaniaGame) -> List[Teleporter]:
     world_list = default_database.game_description_for(game).world_list
     areas = [
         node.teleporter for world in world_list.worlds
         for area in world.areas for node in area.nodes
         if isinstance(node, TeleporterNode) and node.editable
     ]
     areas.sort()
     return areas
示例#21
0
    def bit_pack_encode(self, metadata) -> Iterator[Tuple[int, int]]:
        db = default_database.game_description_for(self.game)

        yield from self.randomization_mode.bit_pack_encode(metadata)
        if self.excluded_indices:
            yield from bitpacking.encode_bool(True)
            yield from bitpacking.pack_sorted_array_elements(self._sorted_indices, _all_indices(db))
        else:
            yield from bitpacking.encode_bool(False)
    async def _show_dialog_for_prime3_layout(self):
        from randovania.games.prime3.patcher import gollop_corruption_patcher
        from randovania.games.prime3.layout.corruption_cosmetic_patches import CorruptionCosmeticPatches
        from randovania.games.prime3.layout.corruption_configuration import CorruptionConfiguration
        from randovania.game_description import default_database

        cosmetic = typing.cast(
            CorruptionCosmeticPatches,
            self._options.options_for_game(RandovaniaGame.METROID_PRIME_CORRUPTION).cosmetic_patches,
        )
        configuration = typing.cast(
            CorruptionConfiguration,
            self.layout_description.get_preset(self.current_player_index).configuration,
        )
        patches = self.layout_description.all_patches[self.current_player_index]
        game = default_database.game_description_for(RandovaniaGame.METROID_PRIME_CORRUPTION)

        pickup_names = []
        for index in range(game.world_list.num_pickup_nodes):
            p_index = PickupIndex(index)
            if p_index in patches.pickup_assignment:
                name = patches.pickup_assignment[p_index].pickup.name
            else:
                name = "Missile Expansion"
            pickup_names.append(name)

        layout_string = gollop_corruption_patcher.layout_string_for_items(pickup_names)
        starting_location = patches.starting_location

        starting_items = patches.starting_items.duplicate()
        starting_items.add_resource_gain([
            (game.resource_database.get_item_by_name("Suit Type"), cosmetic.player_suit.value),
        ])
        if configuration.start_with_corrupted_hypermode:
            hypermode_original = 0
        else:
            hypermode_original = 1

        commands = "\n".join([
            f'set seed="{layout_string}"',
            f'set "starting_items={gollop_corruption_patcher.starting_items_for(starting_items, hypermode_original)}"',
            f'set "starting_location={gollop_corruption_patcher.starting_location_for(game, starting_location)}"',
            f'set "random_door_colors={str(cosmetic.random_door_colors).lower()}"',
            f'set "random_welding_colors={str(cosmetic.random_welding_colors).lower()}"',
        ])
        dialog_text = (
            "There is no integrated patcher for Metroid Prime 3: Corruption games.\n"
            "Download the randomizer for it from #corruption-general in the Metroid Prime Randomizer Discord, "
            "and use the following commands as a seed.\n\n"
            "\n{}").format(commands)

        message_box = ScrollLabelDialog(dialog_text, "Commands for patcher", self)
        message_box.resize(750, 200)
        message_box.label.setTextInteractionFlags(QtCore.Qt.TextSelectableByMouse)
        common_qt_lib.set_clipboard(commands)
        await async_dialog.execute_dialog(message_box)
示例#23
0
def _get_vanilla_translator_configuration(extra_field: str) -> dict[NodeIdentifier, LayoutTranslatorRequirement]:
    from randovania.game_description import default_database
    game = default_database.game_description_for(RandovaniaGame.METROID_PRIME_ECHOES)
    return {
        game.world_list.identifier_for_node(node): LayoutTranslatorRequirement.from_item_short_name(
            node.extra[extra_field]
        )
        for node in game.world_list.iterate_nodes()
        if isinstance(node, ConfigurableNode)
    }
示例#24
0
def area_locations_with_filter(
        game: RandovaniaGame, condition: Callable[[Area],
                                                  bool]) -> List[AreaLocation]:
    world_list = default_database.game_description_for(game).world_list
    areas = [
        AreaLocation(world.world_asset_id, area.area_asset_id)
        for world in world_list.worlds for area in world.areas
        if condition(area)
    ]
    return list(sorted(areas))
示例#25
0
    async def add_commands(self, slash: SlashCommand):
        slash.add_slash_command(
            self.database_command,
            name=self.configuration.get("command_prefix", "") +
            "database-inspect",
            description=
            "Consult the Randovania's logic database for one specific room.",
            guild_ids=None,
            options=[
                manage_commands.create_option(
                    "game",
                    "The game's database to check.",
                    option_type=SlashCommandOptionType.STRING,
                    required=True,
                    choices=[
                        manage_commands.create_choice(game.value,
                                                      game.long_name)
                        for game in enum_lib.iterate_enum(RandovaniaGame)
                    ])
            ],
        )

        def add_id(custom_id: str, call, **kwargs):
            self._on_database_component_listener[
                custom_id] = functools.partial(call, **kwargs)

        for game in enum_lib.iterate_enum(RandovaniaGame):
            db = default_database.game_description_for(game)
            world_options = await create_split_worlds(db)
            self._split_worlds[game] = world_options

            add_id(f"{game.value}_world",
                   self.on_database_world_selected,
                   game=game)
            add_id(f"back_to_{game.value}",
                   self.on_database_back_to_game,
                   game=game)

            for i, split_world in enumerate(world_options):
                add_id(f"{game.value}_world_{i}",
                       self.on_database_area_selected,
                       game=game,
                       split_world=split_world,
                       world_id=i)
                for j, area in enumerate(split_world.areas):
                    add_id(f"{game.value}_world_{i}_area_{j}",
                           self.on_area_node_selection,
                           game=game,
                           area=area)

        slash.add_component_callback(
            self.on_database_component,
            components=list(self._on_database_component_listener.keys()),
            use_callback_name=False,
        )
示例#26
0
def test_committed_human_readable_description(game: RandovaniaGame, tmp_path):
    pretty_print.write_human_readable_game(
        default_database.game_description_for(game), tmp_path)
    new_files = {f.name: f.read_text("utf-8") for f in tmp_path.glob("*.txt")}

    existing_files = {
        f.name: f.read_text("utf-8")
        for f in game.data_path.joinpath("json_data").glob("*.txt")
    }

    assert new_files == existing_files
    def __init__(self, editor: PresetEditor):
        super().__init__(editor)
        item_database = default_database.item_database_for_game(self.game)
        game_description = default_database.game_description_for(self.game)

        size_policy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred,
                                            QtWidgets.QSizePolicy.Fixed)

        self._energy_tank_item = item_database.major_items["Energy Tank"]
        self._create_energy_tank_box(
            game_description.resource_database.energy_tank)
        self._create_pickup_style_box(size_policy)
def test_area_maps(skip_qtbot, canvas: DataEditorCanvas, mocker):
    canvas.select_game(RandovaniaGame.CAVE_STORY)

    for world in default_database.game_description_for(
            RandovaniaGame.CAVE_STORY).world_list.worlds:
        canvas.select_world(world)
        for area in world.areas:
            canvas.select_area(area)
            break
        break

    assert canvas._background_image is not None
示例#29
0
def area_locations_with_filter(
        game: RandovaniaGame,
        condition: Callable[[Area], bool]) -> list[AreaIdentifier]:
    world_list = default_database.game_description_for(game).world_list
    identifiers = [
        AreaIdentifier(
            world_name=world.name,
            area_name=area.name,
        ) for world in world_list.worlds for area in world.areas
        if condition(area)
    ]
    return _sorted_area_identifiers(identifiers)
示例#30
0
def test_cs_item_pool_creator(default_cs_configuration: CSConfiguration,
                              puppies, starting_area):
    game_description = default_database.game_description_for(
        default_cs_configuration.game)
    default_cs_configuration = dataclasses.replace(default_cs_configuration,
                                                   puppies_anywhere=puppies)
    tricks = default_cs_configuration.trick_level.set_level_for_trick(
        game_description.resource_database.get_by_type_and_index(
            ResourceType.TRICK, "SNBubbler"), LayoutTrickLevel.HYPERMODE)
    tricks = tricks.set_level_for_trick(
        game_description.resource_database.get_by_type_and_index(
            ResourceType.TRICK, "SNMissiles"), LayoutTrickLevel.HYPERMODE)
    default_cs_configuration = dataclasses.replace(default_cs_configuration,
                                                   trick_level=tricks)

    base_patches = GamePatches(0, default_cs_configuration, {}, {}, {}, {}, {},
                               {}, starting_area, {})
    rng = Random()

    result = pool_creator.calculate_pool_results(
        default_cs_configuration, game_description.resource_database,
        base_patches, rng)

    # Puppies
    expected_puppies = {"Hajime", "Nene", "Mick", "Shinobu", "Kakeru"}
    names = {pickup.name for pickup in result.assignment.values()}

    assert puppies != names.issuperset(expected_puppies)

    # First Cave Weapon
    first_cave_assignment = [
        pickup for index, pickup in result.assignment.items()
        if index in FIRST_CAVE_INDICES
    ]
    expected_first_cave_len = 1 if starting_area.area_name == "Start Point" else 0

    assert len(first_cave_assignment) == expected_first_cave_len
    assert starting_area.area_name != "Start Point" or first_cave_assignment[
        0].broad_category.name in {"weapon", "missile_related"}

    # Camp weapon/life capsule
    camp_assignment = [
        pickup for index, pickup in result.assignment.items()
        if index in CAMP_INDICES
    ]

    if starting_area.area_name != "Camp":
        assert len(camp_assignment) == 0
    else:
        expected_names = set(STRONG_WEAPONS)
        expected_names.add("5HP Life Capsule")
        for pickup in camp_assignment:
            assert pickup.name in expected_names