def test_basic_search_with_translator_gate(has_translator: bool, echoes_resource_database, echoes_game_patches): # Setup scan_visor = echoes_resource_database.get_item("DarkVisor") nc = functools.partial(NodeIdentifier.create, "Test World", "Test Area A") node_a = GenericNode(nc("Node A"), True, None, "", ("default",), {}) node_b = GenericNode(nc("Node B"), True, None, "", ("default",), {}) node_c = GenericNode(nc("Node C"), True, None, "", ("default",), {}) translator_node = ConfigurableNode(translator_identif := nc("Translator Gate"), True, None, "", ("default",), {}) world_list = WorldList([ World("Test World", [ Area("Test Area A", None, True, [node_a, node_b, node_c, translator_node], { node_a: { node_b: Requirement.trivial(), translator_node: Requirement.trivial(), }, node_b: { node_a: Requirement.trivial(), }, node_c: { translator_node: Requirement.trivial(), }, translator_node: { node_a: Requirement.trivial(), node_c: Requirement.trivial(), }, }, {} ) ], {}) ]) game = GameDescription(RandovaniaGame.METROID_PRIME_ECHOES, DockWeaknessDatabase([], {}, (None, None)), echoes_resource_database, ("default",), Requirement.impossible(), None, {}, None, world_list) patches = echoes_game_patches.assign_node_configuration({ translator_identif: ResourceRequirement(scan_visor, 1, False) }) initial_state = State({scan_visor: 1 if has_translator else 0}, (), 99, node_a, patches, None, StateGameData(echoes_resource_database, game.world_list, 100, 99)) # Run reach = reach_lib.reach_with_all_safe_resources(game, initial_state) # Assert if has_translator: assert set(reach.safe_nodes) == {node_a, node_b, translator_node, node_c} else: assert set(reach.safe_nodes) == {node_a, node_b}
def _do_create_node(self, node_name: str, location: Optional[NodeLocation]): new_node = GenericNode(self._create_identifier(node_name), self.editor.new_node_index(), False, location, "", ("default", ), {}) self.editor.add_node(self.current_area, new_node) self.on_select_area(new_node)
def read_node(self, name: str, data: Dict) -> Node: try: location = None if data["coordinates"] is not None: location = location_from_json(data["coordinates"]) generic_args = { "identifier": NodeIdentifier.create(self.current_world_name, self.current_area_name, name), "heal": data["heal"], "location": location, "description": data["description"], "layers": tuple(data["layers"]), "extra": frozen_lib.wrap(data["extra"]), } node_type: int = data["node_type"] if node_type == "generic": return GenericNode(**generic_args) elif node_type == "dock": return DockNode( **generic_args, dock_type=self.dock_weakness_database.find_type( data["dock_type"]), default_connection=NodeIdentifier.from_json( data["default_connection"]), default_dock_weakness=self.dock_weakness_database. get_by_weakness( data["dock_type"], data["default_dock_weakness"], ), override_default_open_requirement=read_optional_requirement( data["override_default_open_requirement"], self.resource_database), override_default_lock_requirement=read_optional_requirement( data["override_default_lock_requirement"], self.resource_database), ) elif node_type == "pickup": return PickupNode( **generic_args, pickup_index=PickupIndex(data["pickup_index"]), major_location=data["major_location"], ) elif node_type == "teleporter": return TeleporterNode( **generic_args, default_connection=AreaIdentifier.from_json( data["destination"]), keep_name_when_vanilla=data["keep_name_when_vanilla"], editable=data["editable"], ) elif node_type == "event": return EventNode( **generic_args, event=self.resource_database.get_by_type_and_index( ResourceType.EVENT, data["event_name"])) elif node_type == "configurable_node": return ConfigurableNode(**generic_args, ) elif node_type == "logbook": lore_type = LoreType(data["lore_type"]) if lore_type == LoreType.REQUIRES_ITEM: required_translator = self.resource_database.get_item( data["extra"]["translator"]) else: required_translator = None if lore_type in { LoreType.SPECIFIC_PICKUP, LoreType.SKY_TEMPLE_KEY_HINT }: hint_index = data["extra"]["hint_index"] else: hint_index = None return LogbookNode( **generic_args, string_asset_id=data["string_asset_id"], scan_visor=self._get_scan_visor(), lore_type=lore_type, required_translator=required_translator, hint_index=hint_index, ) elif node_type == "player_ship": return PlayerShipNode( **generic_args, is_unlocked=read_requirement(data["is_unlocked"], self.resource_database), item_to_summon=self._get_command_visor(), ) else: raise Exception(f"Unknown type: {node_type}") except Exception as e: raise Exception(f"In node {name}, got error: {e}")
def create_new_node(self) -> Node: node_type = self.node_type_combo.currentData() identifier = dataclasses.replace(self.node.identifier, node_name=self.name_edit.text()) heal = self.heals_check.isChecked() location = None if self.location_group.isChecked(): location = NodeLocation(self.location_x_spin.value(), self.location_y_spin.value(), self.location_z_spin.value()) description = self.description_edit.toMarkdown() extra = json.loads(self.extra_edit.toPlainText()) layers = (self.layers_combo.currentText(),) if node_type == GenericNode: return GenericNode(identifier, heal, location, description, layers, extra) elif node_type == DockNode: connection_node: Node = self.dock_connection_node_combo.currentData() return DockNode( identifier, heal, location, description, layers, extra, self.dock_type_combo.currentData(), self.game.world_list.identifier_for_node(connection_node), self.dock_weakness_combo.currentData(), None, None, ) elif node_type == PickupNode: return PickupNode( identifier, heal, location, description, layers, extra, PickupIndex(self.pickup_index_spin.value()), self.major_location_check.isChecked(), ) elif node_type == TeleporterNode: dest_world: World = self.teleporter_destination_world_combo.currentData() dest_area: Area = self.teleporter_destination_area_combo.currentData() return TeleporterNode( identifier, heal, location, description, layers, extra, AreaIdentifier( world_name=dest_world.name, area_name=dest_area.name, ), self.teleporter_vanilla_name_edit.isChecked(), self.teleporter_editable_check.isChecked(), ) elif node_type == EventNode: event = self.event_resource_combo.currentData() if event is None: raise ValueError("There are no events in the database, unable to create EventNode.") return EventNode( identifier, heal, location, description, layers, extra, event, ) elif node_type == ConfigurableNode: return ConfigurableNode( identifier, heal, location, description, layers, extra, ) elif node_type == LogbookNode: lore_type: LoreType = self.lore_type_combo.currentData() if lore_type == LoreType.REQUIRES_ITEM: required_translator = self.logbook_extra_combo.currentData() if required_translator is None: raise ValueError("Missing required translator.") else: required_translator = None if lore_type == LoreType.SPECIFIC_PICKUP: hint_index = self.logbook_extra_combo.currentData() else: hint_index = None return LogbookNode( identifier, heal, location, description, layers, extra, int(self.logbook_string_asset_id_edit.text(), 0), self._get_scan_visor(), lore_type, required_translator, hint_index ) elif node_type == PlayerShipNode: return PlayerShipNode( identifier, heal, location, description, layers, extra, self._unlocked_by_requirement, self._get_command_visor() ) else: raise RuntimeError(f"Unknown node type: {node_type}")