def test_gate_assignment_for_configuration_all_random(
        echoes_resource_database):
    # Setup
    violet = find_resource_info_with_long_name(echoes_resource_database.item,
                                               "Violet Translator")
    emerald = find_resource_info_with_long_name(echoes_resource_database.item,
                                                "Emerald Translator")

    configuration = MagicMock()
    configuration.translator_configuration.translator_requirement = {
        TranslatorGate(index): LayoutTranslatorRequirement.RANDOM
        for index in [1, 15, 23]
    }

    rng = MagicMock()
    rng.choice.side_effect = [
        LayoutTranslatorRequirement.EMERALD,
        LayoutTranslatorRequirement.VIOLET,
        LayoutTranslatorRequirement.EMERALD,
    ]

    # Run
    results = base_patches_factory.gate_assignment_for_configuration(
        configuration, echoes_resource_database, rng)

    # Assert
    assert results == {
        TranslatorGate(1): emerald,
        TranslatorGate(15): violet,
        TranslatorGate(23): emerald,
    }
Exemple #2
0
    def create_tracker(self):
        self.delete_tracker()
        game_enum = RandovaniaGame.PRIME2

        resource_database = default_database.resource_database_for(game_enum)
        with get_data_path().joinpath(f"gui_assets/tracker/{game_enum.value}.json").open("r") as tracker_details_file:
            tracker_details = json.load(tracker_details_file)

        for element in tracker_details["elements"]:
            text_template = ""

            if "image_path" in element:
                image_path = get_data_path().joinpath(element["image_path"])
                pixmap = QPixmap(str(image_path))

                label = ClickableLabel(self.inventory_group, paint_with_opacity(pixmap, 0.3),
                                       paint_with_opacity(pixmap, 1.0))
                label.set_checked(False)
                label.set_ignore_mouse_events(True)

            elif "label" in element:
                label = QLabel(self.inventory_group)
                label.setAlignment(Qt.AlignCenter)
                text_template = element["label"]

            else:
                raise ValueError(f"Invalid element: {element}")

            resources = [
                find_resource_info_with_long_name(resource_database.item, resource_name)
                for resource_name in element["resources"]
            ]
            self._tracker_elements.append(Element(label, resources, text_template))
            self.inventory_layout.addWidget(label, element["row"], element["column"])
    def __init__(self, game_connection: GameConnection, options: Options):
        super().__init__()
        self.setupUi(self)
        self.game_connection = game_connection
        common_qt_lib.set_default_window_icon(self)

        self.game_data = data_reader.decode_data(
            default_data.decode_default_prime2())
        self._energy_tank_item = find_resource_info_with_long_name(
            self.game_data.resource_database.item, "Energy Tank")

        self._item_to_label: Dict[ItemResourceInfo, ClickableLabel] = {}
        self._labels_for_keys = []
        self.create_tracker()

        self.game_connection_setup = GameConnectionSetup(
            self, self.game_connection_tool, self.connection_status_label,
            self.game_connection, options)
        self.force_update_button.setEnabled(not options.tracking_inventory)
        self.force_update_button.clicked.connect(self.on_force_update_button)

        self._update_timer = QTimer(self)
        self._update_timer.setInterval(100)
        self._update_timer.timeout.connect(self._on_timer_update)
        self._update_timer.setSingleShot(True)
Exemple #4
0
def list_paths_with_resource_logic(args):
    gd = load_game_description(args)

    resource = None
    for resource_type in gd.resource_database:
        try:
            resource = find_resource_info_with_long_name(
                resource_type, args.resource)
            break
        except MissingResource:
            continue

    if resource is None:
        print(f"A resource named {args.resource} was not found.")
        raise SystemExit(1)

    _list_paths_with_resource(gd, args.print_only_area, resource, None)
Exemple #5
0
def logic_bootstrap(
    configuration: LayoutConfiguration,
    game: GameDescription,
    patches: GamePatches,
) -> Tuple[GameDescription, State]:
    """
    Core code for starting a new Logic/State.
    :param configuration:
    :param game:
    :param patches:
    :return:
    """

    # global state for easy printing functions
    debug._gd = game

    game = copy.deepcopy(game)
    starting_state = calculate_starting_state(game, patches)

    if configuration.trick_level_configuration.global_level == LayoutTrickLevel.MINIMAL_RESTRICTIONS:
        major_items_config = configuration.major_items_configuration
        _add_minimal_restrictions_initial_resources(
            starting_state.resources,
            game.resource_database,
            major_items_config.progressive_grapple,
            major_items_config.progressive_suit,
        )

    difficulty_level, static_resources = static_resources_for_layout_logic(
        configuration.trick_level_configuration, game.resource_database)
    add_resources_into_another(starting_state.resources, static_resources)
    add_resources_into_another(
        starting_state.resources,
        _create_vanilla_translator_resources(game.resource_database,
                                             configuration.elevators))
    starting_state.resources[
        game.resource_database.difficulty_resource] = difficulty_level

    # All version differences are patched out from the game
    starting_state.resources[find_resource_info_with_long_name(
        game.resource_database.version, "NTSC")] = 1

    game.patch_requirements(starting_state.resources,
                            configuration.damage_strictness.value)

    return game, starting_state
    def __init__(self, game_connection: GameConnection):
        super().__init__()
        self.setupUi(self)
        self.game_connection = game_connection
        common_qt_lib.set_default_window_icon(self)

        self.game_data = data_reader.decode_data(
            default_data.decode_default_prime2())
        self._energy_tank_item = find_resource_info_with_long_name(
            self.game_data.resource_database.item, "Energy Tank")

        self._item_to_label: Dict[ItemResourceInfo, ClickableLabel] = {}
        self._labels_for_keys = []
        self.create_tracker()

        self._update_timer = QTimer(self)
        self._update_timer.setInterval(100)
        self._update_timer.timeout.connect(self._on_timer_update)
        self._update_timer.setSingleShot(True)
        self.game_connection.StatusUpdated.connect(self._game_status_updated)
def test_gate_assignment_for_configuration_all_emerald(
        echoes_resource_database):
    # Setup
    emerald = find_resource_info_with_long_name(echoes_resource_database.item,
                                                "Emerald Translator")
    indices = [1, 15, 23]

    configuration = MagicMock()
    configuration.translator_configuration.translator_requirement = {
        TranslatorGate(index): LayoutTranslatorRequirement.EMERALD
        for index in indices
    }

    rng = MagicMock()

    # Run
    results = base_patches_factory.gate_assignment_for_configuration(
        configuration, echoes_resource_database, rng)

    # Assert
    assert results == {TranslatorGate(index): emerald for index in indices}
Exemple #8
0
def static_resources_for_layout_logic(
    configuration: TrickLevelConfiguration,
    resource_database: ResourceDatabase,
) -> CurrentResources:
    """
    :param configuration:
    :param resource_database:
    :return:
    """

    static_resources = {}

    for trick in resource_database.trick:
        static_resources[trick] = configuration.level_for_trick(
            trick).as_number

    # Room Rando
    room_rando = find_resource_info_with_long_name(resource_database.misc,
                                                   "Room Randomizer")
    static_resources[room_rando] = 0

    return static_resources
Exemple #9
0
def _create_vanilla_translator_resources(
    resource_database: ResourceDatabase,
    elevators: LayoutElevators,
) -> CurrentResources:
    """

    :param resource_database:
    :param translator_configuration:
    :return:
    """
    events = [
        ("Vanilla GFMC Compound Translator Gate", False),
        ("Vanilla Torvus Temple Translator Gate", False),
        ("Vanilla Great Temple Emerald Translator Gate",
         elevators == LayoutElevators.VANILLA),
    ]

    return {
        find_resource_info_with_long_name(resource_database.misc, name):
        1 if active else 0
        for name, active in events
    }
def test_bit_pack_pickup_entry(has_convert: bool, echoes_resource_database):
    # Setup
    name = "Some Random Name"
    if has_convert:
        convert_resources = (ResourceConversion(
            find_resource_info_with_long_name(echoes_resource_database.item,
                                              "Morph Ball"),
            find_resource_info_with_long_name(echoes_resource_database.item,
                                              "Item Percentage")), )
    else:
        convert_resources = ()

    pickup = PickupEntry(
        name=name,
        model_index=26,
        item_category=ItemCategory.TEMPLE_KEY,
        broad_category=ItemCategory.KEY,
        resources=(ConditionalResources(
            "Morph Ball",
            None,
            (
                (find_resource_info_with_long_name(
                    echoes_resource_database.item, "Morph Ball"), 2),
                (find_resource_info_with_long_name(
                    echoes_resource_database.item, "Item Percentage"), 5),
            ),
        ),
                   ConditionalResources(
                       "Grapple Beam",
                       find_resource_info_with_long_name(
                           echoes_resource_database.item, "Morph Ball"),
                       ((find_resource_info_with_long_name(
                           echoes_resource_database.item,
                           "Grapple Beam"), 3), ),
                   )),
        convert_resources=convert_resources)

    # Run
    encoded = bitpacking.pack_value(
        BitPackPickupEntry(pickup, echoes_resource_database))
    decoder = BitPackDecoder(encoded)
    decoded = BitPackPickupEntry.bit_pack_unpack(decoder, name,
                                                 echoes_resource_database)

    # Assert
    assert pickup == decoded
Exemple #11
0
def _create_vanilla_translator_resources(
    resource_database: ResourceDatabase,
    translator_configuration: TranslatorConfiguration,
) -> CurrentResources:
    """

    :param resource_database:
    :param translator_configuration:
    :return:
    """
    events = [
        ("Vanilla GFMC Compound Translator Gate",
         not translator_configuration.fixed_gfmc_compound),
        ("Vanilla Torvus Temple Translator Gate",
         not translator_configuration.fixed_torvus_temple),
        ("Vanilla Great Temple Emerald Translator Gate",
         not translator_configuration.fixed_great_temple),
    ]

    return {
        find_resource_info_with_long_name(resource_database.trick, name):
        1 if active else 0
        for name, active in events
    }
Exemple #12
0
    def read_node(self, data: Dict) -> Node:
        name: str = data["name"]
        heal: bool = data["heal"]
        node_type: int = data["node_type"]
        self.generic_index += 1

        if node_type == 0:
            return GenericNode(name, heal, self.generic_index)

        elif node_type == 1:
            return DockNode(
                name, heal, self.generic_index, data["dock_index"],
                DockConnection(data["connected_area_asset_id"],
                               data["connected_dock_index"]),
                self.dock_weakness_database.get_by_type_and_index(
                    DockType(data["dock_type"]), data["dock_weakness_index"]))

        elif node_type == 2:
            return PickupNode(name, heal, self.generic_index,
                              PickupIndex(data["pickup_index"]),
                              data["major_location"])

        elif node_type == 3:
            instance_id = data["teleporter_instance_id"]

            destination_world_asset_id = data["destination_world_asset_id"]
            destination_area_asset_id = data["destination_area_asset_id"]

            return TeleporterNode(
                name,
                heal,
                self.generic_index,
                instance_id,
                AreaLocation(destination_world_asset_id,
                             destination_area_asset_id),
                data["keep_name_when_vanilla"],
                data["editable"],
            )

        elif node_type == 4:
            return EventNode(
                name, heal, self.generic_index,
                self.resource_database.get_by_type_and_index(
                    ResourceType.EVENT, data["event_index"]))

        elif node_type == 5:
            return TranslatorGateNode(
                name, heal, self.generic_index,
                TranslatorGate(data["gate_index"]),
                find_resource_info_with_long_name(self.resource_database.item,
                                                  "Scan Visor"))

        elif node_type == 6:
            lore_type = list(LoreType)[data["lore_type"]]

            if lore_type == LoreType.LUMINOTH_LORE:
                required_translator = self.resource_database.get_item(
                    data["extra"])
            else:
                required_translator = None

            if lore_type in {
                    LoreType.LUMINOTH_WARRIOR, LoreType.SKY_TEMPLE_KEY_HINT
            }:
                hint_index = data["extra"]
            else:
                hint_index = None

            return LogbookNode(
                name, heal, self.generic_index, data["string_asset_id"],
                find_resource_info_with_long_name(self.resource_database.item,
                                                  "Scan Visor"), lore_type,
                required_translator, hint_index)

        else:
            raise Exception("Unknown node type: {}".format(node_type))
Exemple #13
0
def _patches_with_data(request, echoes_game_data, echoes_item_database):
    game = data_reader.decode_data(echoes_game_data)

    data = {
        "starting_location": "Temple Grounds/Landing Site",
        "starting_items": {},
        "elevators": {
            "Temple Grounds/Temple Transport C": "Great Temple/Temple Transport C",
            "Temple Grounds/Transport to Agon Wastes": "Agon Wastes/Transport to Temple Grounds",
            "Temple Grounds/Transport to Torvus Bog": "Torvus Bog/Transport to Temple Grounds",
            "Temple Grounds/Temple Transport B": "Great Temple/Temple Transport B",
            "Temple Grounds/Transport to Sanctuary Fortress": "Sanctuary Fortress/Transport to Temple Grounds",
            "Temple Grounds/Temple Transport A": "Great Temple/Temple Transport A",
            "Great Temple/Temple Transport A": "Temple Grounds/Temple Transport A",
            "Great Temple/Temple Transport C": "Temple Grounds/Temple Transport C",
            "Great Temple/Temple Transport B": "Temple Grounds/Temple Transport B",
            "Sky Temple Grounds/Sky Temple Gateway": "Sky Temple/Sky Temple Energy Controller",
            "Sky Temple/Sky Temple Energy Controller": "Sky Temple Grounds/Sky Temple Gateway",
            "Agon Wastes/Transport to Temple Grounds": "Temple Grounds/Transport to Agon Wastes",
            "Agon Wastes/Transport to Torvus Bog": "Torvus Bog/Transport to Agon Wastes",
            "Agon Wastes/Transport to Sanctuary Fortress": "Sanctuary Fortress/Transport to Agon Wastes",
            "Torvus Bog/Transport to Temple Grounds": "Temple Grounds/Transport to Torvus Bog",
            "Torvus Bog/Transport to Agon Wastes": "Agon Wastes/Transport to Torvus Bog",
            "Torvus Bog/Transport to Sanctuary Fortress": "Sanctuary Fortress/Transport to Torvus Bog",
            "Sanctuary Fortress/Transport to Temple Grounds": "Temple Grounds/Transport to Sanctuary Fortress",
            "Sanctuary Fortress/Transport to Agon Wastes": "Agon Wastes/Transport to Sanctuary Fortress",
            "Sanctuary Fortress/Transport to Torvus Bog": "Torvus Bog/Transport to Sanctuary Fortress",
            "Sanctuary Fortress/Aerie": "Sanctuary Fortress/Aerie Transport Station",
            "Sanctuary Fortress/Aerie Transport Station": "Sanctuary Fortress/Aerie",
        },
        "translators": {},
        "locations": {},
        "hints": {},
        "_locations_internal": "",
    }
    patches = game.create_game_patches()

    locations = collections.defaultdict(dict)
    for world, area, node in game.world_list.all_worlds_areas_nodes:
        if node.is_resource_node and isinstance(node, PickupNode):
            world_name = world.dark_name if area.in_dark_aether else world.name
            locations[world_name][game.world_list.node_name(node)] = game_patches_serializer._ETM_NAME

    data["locations"] = {
        world: {
            area: item
            for area, item in sorted(locations[world].items())
        }
        for world in sorted(locations.keys())
    }

    if request.param.get("starting_item"):
        item_name = request.param.get("starting_item")
        patches = patches.assign_extra_initial_items({
            find_resource_info_with_long_name(game.resource_database.item, item_name): 1,
        })
        data["starting_items"][item_name] = 1

    if request.param.get("elevator"):
        elevator_id, elevator_source = request.param.get("elevator")
        elevator_connection = copy.copy(patches.elevator_connection)
        elevator_connection[elevator_id] = game.starting_location

        patches = dataclasses.replace(patches, elevator_connection=elevator_connection)
        data["elevators"][elevator_source] = "Temple Grounds/Landing Site"

    if request.param.get("translator"):
        gates = {}
        for index, gate_name, translator in request.param.get("translator"):
            gates[TranslatorGate(index)] = find_resource_info_with_long_name(game.resource_database.item, translator)
            data["translators"][gate_name] = translator

        patches = patches.assign_gate_assignment(gates)

    if request.param.get("pickup"):
        data["_locations_internal"], pickup_name = request.param.get("pickup")
        pickup = pickup_creator.create_major_item(echoes_item_database.major_items[pickup_name],
                                                  MajorItemState(), True, game.resource_database,
                                                  None, False)

        patches = patches.assign_new_pickups([(PickupIndex(5), pickup)])
        data["locations"]["Temple Grounds"]['Transport to Agon Wastes/Pickup (Missile)'] = pickup_name

    if request.param.get("hint"):
        asset, hint = request.param.get("hint")
        patches = patches.assign_hint(LogbookAsset(asset), Hint.from_json(hint))
        data["hints"][str(asset)] = hint

    return data, patches
Exemple #14
0
 def _get_command_visor(self) -> ItemResourceInfo:
     return find_resource_info_with_long_name(self.resource_database.item,
                                              "Command Visor")
def _patches_with_data(request, echoes_game_data, echoes_item_database):
    game = data_reader.decode_data(echoes_game_data)

    data = {
        "starting_location": "Temple Grounds/Landing Site",
        "starting_items": {},
        "elevators": {
            "Temple Grounds/Temple Transport C":
            "Great Temple/Temple Transport C",
            "Temple Grounds/Transport to Agon Wastes":
            "Agon Wastes/Transport to Temple Grounds",
            "Temple Grounds/Transport to Torvus Bog":
            "Torvus Bog/Transport to Temple Grounds",
            "Temple Grounds/Temple Transport B":
            "Great Temple/Temple Transport B",
            "Temple Grounds/Sky Temple Gateway":
            "Great Temple/Sky Temple Energy Controller",
            "Temple Grounds/Transport to Sanctuary Fortress":
            "Sanctuary Fortress/Transport to Temple Grounds",
            "Temple Grounds/Temple Transport A":
            "Great Temple/Temple Transport A",
            "Great Temple/Temple Transport A":
            "Temple Grounds/Temple Transport A",
            "Great Temple/Temple Transport C":
            "Temple Grounds/Temple Transport C",
            "Great Temple/Temple Transport B":
            "Temple Grounds/Temple Transport B",
            "Great Temple/Sky Temple Energy Controller":
            "Temple Grounds/Sky Temple Gateway",
            "Agon Wastes/Transport to Temple Grounds":
            "Temple Grounds/Transport to Agon Wastes",
            "Agon Wastes/Transport to Torvus Bog":
            "Torvus Bog/Transport to Agon Wastes",
            "Agon Wastes/Transport to Sanctuary Fortress":
            "Sanctuary Fortress/Transport to Agon Wastes",
            "Torvus Bog/Transport to Temple Grounds":
            "Temple Grounds/Transport to Torvus Bog",
            "Torvus Bog/Transport to Agon Wastes":
            "Agon Wastes/Transport to Torvus Bog",
            "Torvus Bog/Transport to Sanctuary Fortress":
            "Sanctuary Fortress/Transport to Torvus Bog",
            "Sanctuary Fortress/Transport to Temple Grounds":
            "Temple Grounds/Transport to Sanctuary Fortress",
            "Sanctuary Fortress/Transport to Agon Wastes":
            "Agon Wastes/Transport to Sanctuary Fortress",
            "Sanctuary Fortress/Transport to Torvus Bog":
            "Torvus Bog/Transport to Sanctuary Fortress"
        },
        "translators": {},
        "locations": {
            world.name: {
                game.world_list.node_name(node): "Nothing"
                for node in world.all_nodes
                if node.is_resource_node and isinstance(node, PickupNode)
            }
            for world in sorted(game.world_list.worlds, key=lambda w: w.name)
        },
        "hints": {},
        "_locations_internal": "",
    }
    patches = GamePatches.with_game(game)

    if request.param.get("starting_item"):
        item_name = request.param.get("starting_item")
        patches = patches.assign_extra_initial_items({
            find_resource_info_with_long_name(game.resource_database.item, item_name):
            1,
        })
        data["starting_items"][item_name] = 1

    if request.param.get("elevator"):
        elevator_id, elevator_source = request.param.get("elevator")
        elevator_connection = copy.copy(patches.elevator_connection)
        elevator_connection[elevator_id] = game.starting_location

        patches = dataclasses.replace(patches,
                                      elevator_connection=elevator_connection)
        data["elevators"][elevator_source] = "Temple Grounds/Landing Site"

    if request.param.get("translator"):
        gates = {}
        for index, gate_name, translator in request.param.get("translator"):
            gates[TranslatorGate(index)] = find_resource_info_with_long_name(
                game.resource_database.item, translator)
            data["translators"][gate_name] = translator

        patches = patches.assign_gate_assignment(gates)

    if request.param.get("pickup"):
        data["_locations_internal"], pickup_name = request.param.get("pickup")
        pickup = pickup_creator.create_major_item(
            echoes_item_database.major_items[pickup_name], MajorItemState(),
            True, game.resource_database, None, False)

        patches = patches.assign_new_pickups([(PickupIndex(5), pickup)])
        data["locations"]["Temple Grounds"][
            'Transport to Agon Wastes/Pickup (Missile)'] = pickup_name

    if request.param.get("hint"):
        asset, hint = request.param.get("hint")
        patches = patches.assign_hint(LogbookAsset(asset),
                                      Hint.from_json(hint))
        data["hints"][str(asset)] = hint

    return data, patches
Exemple #16
0
def decode_single(player_index: int, num_players: int, game_modifications: dict,
                  configuration: LayoutConfiguration) -> GamePatches:
    """
    Decodes a dict created by `serialize` back into a GamePatches.
    :param game_modifications:
    :param player_index:
    :param num_players:
    :param configuration:
    :return:
    """
    game = data_reader.decode_data(configuration.game_data)
    game_specific = dataclasses.replace(
        game.game_specific,
        energy_per_tank=configuration.energy_per_tank,
        beam_configurations=configuration.beam_configuration.create_game_specific(game.resource_database))

    world_list = game.world_list

    # Starting Location
    starting_location = _area_name_to_area_location(world_list, game_modifications["starting_location"])

    # Initial items
    starting_items = {
        find_resource_info_with_long_name(game.resource_database.item, resource_name): quantity
        for resource_name, quantity in game_modifications["starting_items"].items()
    }

    # Elevators
    elevator_connection = {}
    for source_name, target_name in game_modifications["elevators"].items():
        source_area = _area_name_to_area_location(world_list, source_name)
        target_area = _area_name_to_area_location(world_list, target_name)

        potential_source_nodes = [
            node
            for node in world_list.area_by_area_location(source_area).nodes
            if isinstance(node, TeleporterNode)
        ]
        assert len(potential_source_nodes) == 1
        source_node = potential_source_nodes[0]
        elevator_connection[source_node.teleporter_instance_id] = target_area

    # Translator Gates
    translator_gates = {
        _find_gate_with_name(gate_name): find_resource_info_with_long_name(game.resource_database.item, resource_name)
        for gate_name, resource_name in game_modifications["translators"].items()
    }

    # Pickups
    target_name_re = re.compile(r"(.*) for Player \d+")

    index_to_pickup_name = {}
    for world_name, world_data in game_modifications["locations"].items():
        for area_node_name, target_name in world_data.items():
            if target_name == _ETM_NAME:
                continue

            pickup_name_match = target_name_re.match(target_name)
            if pickup_name_match is not None:
                pickup_name = pickup_name_match.group(1)
            else:
                pickup_name = target_name

            node = world_list.node_from_name(f"{world_name}/{area_node_name}")
            assert isinstance(node, PickupNode)
            index_to_pickup_name[node.pickup_index] = pickup_name

    decoder = BitPackDecoder(base64.b64decode(game_modifications["_locations_internal"].encode("utf-8"), validate=True))
    pickup_assignment = dict(BitPackPickupEntryList.bit_pack_unpack(decoder, {
        "index_mapping": index_to_pickup_name,
        "num_players": num_players,
        "database": game.resource_database,
    }).value)

    # Hints
    hints = {}
    for asset_id, hint in game_modifications["hints"].items():
        hints[LogbookAsset(int(asset_id))] = Hint.from_json(hint)

    return GamePatches(
        player_index=player_index,
        pickup_assignment=pickup_assignment,  # PickupAssignment
        elevator_connection=elevator_connection,  # Dict[int, AreaLocation]
        dock_connection={},  # Dict[Tuple[int, int], DockConnection]
        dock_weakness={},  # Dict[Tuple[int, int], DockWeakness]
        translator_gates=translator_gates,
        starting_items=starting_items,  # ResourceGainTuple
        starting_location=starting_location,  # AreaLocation
        hints=hints,
        game_specific=game_specific,
    )
Exemple #17
0
def decode(game_modifications: dict,
           configuration: LayoutConfiguration) -> GamePatches:
    """
    Decodes a dict created by `serialize` back into a GamePatches.
    :param game_modifications:
    :param configuration:
    :return:
    """
    game = data_reader.decode_data(configuration.game_data)
    world_list = game.world_list

    # Starting Location
    starting_location = _area_name_to_area_location(
        world_list, game_modifications["starting_location"])

    # Initial items
    starting_items = {
        find_resource_info_with_long_name(game.resource_database.item,
                                          resource_name): quantity
        for resource_name, quantity in
        game_modifications["starting_items"].items()
    }

    # Elevators
    elevator_connection = {}
    for source_name, target_name in game_modifications["elevators"].items():
        source_area = _area_name_to_area_location(world_list, source_name)
        target_area = _area_name_to_area_location(world_list, target_name)

        potential_source_nodes = [
            node
            for node in world_list.area_by_area_location(source_area).nodes
            if isinstance(node, TeleporterNode)
        ]
        assert len(potential_source_nodes) == 1
        source_node = potential_source_nodes[0]
        elevator_connection[source_node.teleporter_instance_id] = target_area

    # Translator Gates
    translator_gates = {
        _find_gate_with_name(gate_name):
        find_resource_info_with_long_name(game.resource_database.item,
                                          resource_name)
        for gate_name, resource_name in
        game_modifications["translators"].items()
    }

    # Pickups
    pickup_assignment = {}
    decoder = BitPackDecoder(
        base64.b64decode(
            game_modifications["_locations_internal"].encode("utf-8"),
            validate=True))

    for world_name, world_data in game_modifications["locations"].items():
        for area_node_name, pickup_name in world_data.items():
            if pickup_name == "Nothing":
                continue

            node = world_list.node_from_name(f"{world_name}/{area_node_name}")
            assert isinstance(node, PickupNode)

            pickup = BitPackPickupEntry.bit_pack_unpack(
                decoder, pickup_name, game.resource_database)
            pickup_assignment[node.pickup_index] = pickup

    # Hints
    hints = {}
    for asset_id, hint in game_modifications["hints"].items():
        hints[LogbookAsset(int(asset_id))] = Hint.from_json(hint)

    return GamePatches(
        pickup_assignment=pickup_assignment,  # PickupAssignment
        elevator_connection=elevator_connection,  # Dict[int, AreaLocation]
        dock_connection={},  # Dict[Tuple[int, int], DockConnection]
        dock_weakness={},  # Dict[Tuple[int, int], DockWeakness]
        translator_gates=translator_gates,
        starting_items=starting_items,  # ResourceGainTuple
        starting_location=starting_location,  # AreaLocation
        hints=hints,
    )
 def find_resource(name: str):
     return find_resource_info_with_long_name(
         self.game_data.resource_database.item, name)
Exemple #19
0
 def _get_scan_visor(self) -> ItemResourceInfo:
     return find_resource_info_with_long_name(self.resource_database.item,
                                              "Scan Visor")
Exemple #20
0
def decode_single(player_index: int, all_pools: Dict[int, PoolResults],
                  game: GameDescription, game_modifications: dict,
                  configuration: LayoutConfiguration) -> GamePatches:
    """
    Decodes a dict created by `serialize` back into a GamePatches.
    :param player_index:
    :param all_pools:
    :param game:
    :param game_modifications:
    :param configuration:
    :return:
    """
    game_specific = base_patches_factory.create_game_specific(
        configuration, game)
    world_list = game.world_list

    initial_pickup_assignment = all_pools[player_index].assignment

    # Starting Location
    starting_location = _area_name_to_area_location(
        world_list, game_modifications["starting_location"])

    # Initial items
    starting_items = {
        find_resource_info_with_long_name(game.resource_database.item,
                                          resource_name): quantity
        for resource_name, quantity in
        game_modifications["starting_items"].items()
    }

    # Elevators
    elevator_connection = {}
    for source_name, target_name in game_modifications["elevators"].items():
        source_area = _area_name_to_area_location(world_list, source_name)
        target_area = _area_name_to_area_location(world_list, target_name)

        potential_source_nodes = [
            node
            for node in world_list.area_by_area_location(source_area).nodes
            if isinstance(node, TeleporterNode)
        ]
        assert len(potential_source_nodes) == 1
        source_node = potential_source_nodes[0]
        elevator_connection[source_node.teleporter_instance_id] = target_area

    # Translator Gates
    translator_gates = {
        _find_gate_with_name(gate_name):
        find_resource_info_with_long_name(game.resource_database.item,
                                          resource_name)
        for gate_name, resource_name in
        game_modifications["translators"].items()
    }

    # Pickups
    target_name_re = re.compile(r"(.*) for Player (\d+)")

    pickup_assignment: PickupAssignment = {}
    for world_name, world_data in game_modifications["locations"].items():
        for area_node_name, target_name in world_data.items():
            if target_name == _ETM_NAME:
                continue

            pickup_name_match = target_name_re.match(target_name)
            if pickup_name_match is not None:
                pickup_name = pickup_name_match.group(1)
                target_player = int(pickup_name_match.group(2))
            else:
                pickup_name = target_name
                target_player = 0

            node = world_list.node_from_name(f"{world_name}/{area_node_name}")
            assert isinstance(node, PickupNode)
            if node.pickup_index in initial_pickup_assignment:
                pickup = initial_pickup_assignment[node.pickup_index]
                if (pickup_name, target_player) != (pickup.name, player_index):
                    raise ValueError(
                        f"{area_node_name} should be vanilla based on configuration"
                    )

            elif pickup_name != _ETM_NAME:
                configuration_item_pool = all_pools[target_player].pickups
                pickup = _find_pickup_with_name(configuration_item_pool,
                                                pickup_name)
                configuration_item_pool.remove(pickup)
            else:
                pickup = None

            if pickup is not None:
                pickup_assignment[node.pickup_index] = PickupTarget(
                    pickup, target_player)

    # Hints
    hints = {}
    for asset_id, hint in game_modifications["hints"].items():
        hints[LogbookAsset(int(asset_id))] = Hint.from_json(hint)

    return GamePatches(
        player_index=player_index,
        pickup_assignment=pickup_assignment,  # PickupAssignment
        elevator_connection=elevator_connection,  # Dict[int, AreaLocation]
        dock_connection={},  # Dict[Tuple[int, int], DockConnection]
        dock_weakness={},  # Dict[Tuple[int, int], DockWeakness]
        translator_gates=translator_gates,
        starting_items=starting_items,  # ResourceGainTuple
        starting_location=starting_location,  # AreaLocation
        hints=hints,
        game_specific=game_specific,
    )