def test_replace_node(game_editor): # Setup world_list = game_editor.game.world_list loc = AreaIdentifier("Temple Grounds", "Landing Site") loc2 = AreaIdentifier("Temple Grounds", "Service Access") landing_site = world_list.area_by_area_location(loc) source = landing_site.node_with_name("Save Station") door = landing_site.node_with_name("Door to Service Access") assert isinstance(door, DockNode) req = landing_site.connections[source][door] new_node = dataclasses.replace( door, identifier=door.identifier.renamed("FooBar")) # Run game_editor.replace_node(landing_site, door, new_node) # Assert assert world_list.area_by_area_location( loc).connections[source][new_node] is req dock_to_landing = world_list.area_by_area_location(loc2).node_with_name( "Door to Landing Site") assert isinstance(dock_to_landing, DockNode) assert dock_to_landing.default_connection.node_name == "FooBar"
def _starting_location_on_select_classic(self): classics = [ AreaIdentifier("Mimiga Village", "Start Point"), AreaIdentifier("Mimiga Village", "Arthur's House"), AreaIdentifier("Labyrinth", "Camp") ] with self._editor as editor: editor.set_configuration_field( "starting_location", editor.configuration.starting_location.with_elements( classics, self.game_enum))
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 []
def test_create_message_for_hint_relative_area(echoes_game_patches, blank_pickup, players_config, echoes_hint_exporter, offset, distance_text): patches = echoes_game_patches.assign_new_pickups([ (PickupIndex(5), PickupTarget(blank_pickup, 0)), ]) hint = Hint( HintType.LOCATION, PrecisionPair(HintLocationPrecision.RELATIVE_TO_AREA, HintItemPrecision.DETAILED, include_owner=False, relative=RelativeDataArea( offset, AreaIdentifier("Torvus Bog", "Great Bridge"), HintRelativeAreaName.NAME)), PickupIndex(5)) namer = EchoesHintNamer({0: patches}, PlayersConfiguration(0, {0: "You"})) exporter = HintExporter(namer, random.Random(0), ["A Joke"]) # Run result = exporter.create_message_for_hint(hint, {0: patches}, players_config, True) # Assert assert result == ( f'The &push;&main-color=#FF6705B3;Blank Pickup&pop; can be found ' f'&push;&main-color=#FF3333;{distance_text} {10 + (offset or 0)} rooms&pop; away from ' f'Torvus Bog - Great Bridge.')
def test_create_spawn_point_field(echoes_game_description, empty_patches): # Setup resource_db = echoes_game_description.resource_database loc = AreaIdentifier("Temple Grounds", "Hive Chamber B") patches = empty_patches.assign_starting_location(loc).assign_extra_initial_items({ resource_db.get_by_type_and_index(ResourceType.ITEM, "MorphBall"): 3, }) capacities = [ {'amount': 3 if item.short_name == "MorphBall" else 0, 'index': item.extra["item_id"]} for item in resource_db.item ] # Run result = patch_data_factory._create_spawn_point_field(patches, echoes_game_description) # Assert assert result == { "location": { "world_asset_id": 1006255871, "area_asset_id": 494654382, }, "amount": capacities, "capacity": capacities, }
def test_rename_area(game_editor): # Setup world_list = game_editor.game.world_list loc_1 = AreaIdentifier("Temple Grounds", "Transport to Agon Wastes") loc_2 = AreaIdentifier("Agon Wastes", "Transport to Temple Grounds") final = AreaIdentifier("Temple Grounds", "Foo Bar Transportation") # Run game_editor.rename_area(world_list.area_by_area_location(loc_1), "Foo Bar Transportation") # Assert assert world_list.area_by_area_location(final) is not None area_2 = world_list.area_by_area_location(loc_2) assert area_2.node_with_name( "Elevator to Temple Grounds - Foo Bar Transportation") is not None
def decode_data_with_world_reader( data: Dict) -> Tuple[WorldReader, GameDescription]: data = game_migration.migrate_to_current(copy.deepcopy(data)) game = RandovaniaGame(data["game"]) resource_database = read_resource_database(game, data["resource_database"]) dock_weakness_database = read_dock_weakness_database( data["dock_weakness_database"], resource_database) layers = frozen_lib.wrap(data["layers"]) world_reader = WorldReader(resource_database, dock_weakness_database) world_list = world_reader.read_world_list(data["worlds"]) victory_condition = read_requirement(data["victory_condition"], resource_database) starting_location = AreaIdentifier.from_json(data["starting_location"]) initial_states = read_initial_states(data["initial_states"], resource_database) minimal_logic = read_minimal_logic_db(data["minimal_logic"]) return world_reader, GameDescription( game=game, resource_database=resource_database, layers=layers, dock_weakness_database=dock_weakness_database, world_list=world_list, victory_condition=victory_condition, starting_location=starting_location, initial_states=initial_states, minimal_logic=minimal_logic, )
def test_add_elevator_connections_to_patches_vanilla(echoes_game_description, skip_final_bosses: bool, default_echoes_configuration, echoes_game_patches): # Setup patches_factory = echoes_game_description.game.generator.base_patches_factory expected = dataclasses.replace(echoes_game_patches, elevator_connection=echoes_game_description.get_default_elevator_connection()) if skip_final_bosses: node_ident = NodeIdentifier.create("Temple Grounds", "Sky Temple Gateway", "Teleport to Great Temple - Sky Temple Energy Controller") expected.elevator_connection[node_ident] = AreaIdentifier("Temple Grounds", "Credits") config = default_echoes_configuration config = dataclasses.replace(config, elevators=dataclasses.replace(config.elevators, skip_final_bosses=skip_final_bosses)) # Run result = patches_factory.add_elevator_connections_to_patches( config, Random(0), echoes_game_patches) # Assert assert result == expected
def test_create_new_dock(skip_qtbot, tmp_path, blank_game_data): db_path = Path(tmp_path.joinpath("test-game", "game")) game_data = default_data.read_json_then_binary(RandovaniaGame.BLANK)[1] window = DataEditorWindow(game_data, db_path, True, True) window.set_warning_dialogs_disabled(True) skip_qtbot.addWidget(window) window.focus_on_area_by_name("Back-Only Lock Room") current_area = window.current_area target_area = window.game_description.world_list.area_by_area_location( AreaIdentifier("Intro", "Explosive Depot")) assert current_area.node_with_name("Dock to Explosive Depot") is None assert target_area.node_with_name("Dock to Back-Only Lock Room") is None # Run window._create_new_dock(NodeLocation(0, 0, 0), target_area) # Assert new_node = current_area.node_with_name("Dock to Explosive Depot") assert new_node is not None assert window.current_node is new_node assert target_area.node_with_name( "Dock to Back-Only Lock Room") is not None
def test_replace_node_unknown_node(game_editor): # Setup world_list = game_editor.game.world_list loc = AreaIdentifier("Temple Grounds", "Landing Site") loc2 = AreaIdentifier("Temple Grounds", "Service Access") landing_site = world_list.area_by_area_location(loc) dock = world_list.area_by_area_location(loc2).node_with_name( "Door to Landing Site") # Run with pytest.raises( ValueError, match= "Given Door to Landing Site does does not belong to Landing Site." ): game_editor.replace_node(landing_site, dock, dock)
def _area_name_to_area_location(world_list: WorldList, area_name: str) -> AreaIdentifier: world_name, area_name = re.match("([^/]+)/([^/]+)", area_name).group(1, 2) # Filter out dark world names world_name = world_list.world_with_name(world_name).name return AreaIdentifier(world_name, area_name)
def test_one_way_elevator_connections(echoes_game_description, replacement, expected): # Setup rng = random.Random(5000) target_locations = [AreaIdentifier(f"w{i}", f"a{i}") for i in range(6)] elevators = [ ElevatorHelper(NodeIdentifier.create(f"w{i}", f"a{i}", f"n{i}"), AreaIdentifier(f"w{i}", f"a{i}")) for i in range(6) ] database = tuple(elevators) # Run result = elevator_distributor.one_way_elevator_connections( rng, database, target_locations, replacement) # Assert assert result == expected
def static_teleporters(self) -> Dict[NodeIdentifier, AreaIdentifier]: static = {} if self.skip_final_bosses: if self.game == RandovaniaGame.METROID_PRIME: crater = NodeIdentifier.create( "Tallon Overworld", "Artifact Temple", "Teleport to Impact Crater - Crater Impact Point") static[crater] = AreaIdentifier("End of Game", "Credits") elif self.game == RandovaniaGame.METROID_PRIME_ECHOES: gateway = NodeIdentifier.create( "Temple Grounds", "Sky Temple Gateway", "Teleport to Great Temple - Sky Temple Energy Controller") static[gateway] = AreaIdentifier("Temple Grounds", "Credits") else: raise ValueError( f"Unsupported skip_final_bosses and {self.game}") return static
def _location_with_data(request, mocker, echoes_game_description): world_list = echoes_game_description.world_list areas = list(itertools.islice( (AreaIdentifier(world.name, area.name) for world in world_list.worlds for area in world.areas if area.valid_starting_location), 15)) mocker.patch("randovania.layout.lib.location_list.LocationList.areas_list", return_value=list(sorted(areas))) return request.param["encoded"], LocationList.from_json(request.param["json"], RandovaniaGame.METROID_PRIME_ECHOES)
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)
def test_edit_connections(game_editor): # Setup landing_site = game_editor.game.world_list.area_by_area_location( AreaIdentifier("Temple Grounds", "Landing Site")) source = landing_site.node_with_name("Save Station") target = landing_site.node_with_name("Door to Service Access") assert landing_site.connections[source][target] != Requirement.trivial() # Run game_editor.edit_connections(landing_site, source, target, Requirement.trivial()) # Assert assert landing_site.connections[source][target] == Requirement.trivial()
def test_add_relative_hint(echoes_game_description, echoes_game_patches, precise_distance, location_precision, echoes_item_database): # Setup rng = Random(5000) target_precision = MagicMock(spec=HintItemPrecision) precision = MagicMock(spec=HintItemPrecision) patches = echoes_game_patches.assign_new_pickups([ (PickupIndex(8), PickupTarget( _make_pickup(echoes_item_database.item_categories["movement"]), 0)), ]) hint_distributor = EchoesHintDistributor() if location_precision == HintLocationPrecision.RELATIVE_TO_AREA: max_distance = 8 data = RelativeDataArea( None if precise_distance else 3, # Was Industrial Site AreaIdentifier("Temple Grounds", "Hive Chamber A"), precision, ) else: max_distance = 20 data = RelativeDataItem( None if precise_distance else 11, PickupIndex(8), precision, ) # Run result = hint_distributor.add_relative_hint( echoes_game_description.world_list, patches, rng, PickupIndex(1), target_precision, location_precision, precise_distance, precision, max_distance=max_distance, ) # Assert pair = PrecisionPair(location_precision, target_precision, include_owner=False, relative=data) assert result == Hint(HintType.LOCATION, pair, PickupIndex(1))
def test_quick_fill_cs_classic(skip_qtbot, preset_manager): # Setup base = preset_manager.default_preset_for_game( RandovaniaGame.CAVE_STORY).get_preset() preset = dataclasses.replace( base, uuid=uuid.UUID('b41fde84-1f57-4b79-8cd6-3e5a78077fa6'), base_preset_uuid=base.uuid) editor = PresetEditor(preset) window = PresetCSStartingArea( editor, default_database.game_description_for(preset.game)) skip_qtbot.addWidget(window) # Run skip_qtbot.mouseClick(window.starting_area_quick_fill_classic, QtCore.Qt.LeftButton) # Assert expected = { AreaIdentifier("Mimiga Village", "Start Point"), AreaIdentifier("Mimiga Village", "Arthur's House"), AreaIdentifier("Labyrinth", "Camp") } assert set(editor.configuration.starting_location.locations) == expected
def test_remove_node(game_editor): # Setup world_list = game_editor.game.world_list loc = AreaIdentifier("Temple Grounds", "Landing Site") landing_site = world_list.area_by_area_location(loc) node = landing_site.node_with_name("Door to Service Access") assert node is not None # Run game_editor.remove_node(landing_site, node) # Assert assert world_list.area_by_area_location(loc).node_with_name( "Door to Service Access") is None
def test_two_way_elevator_connections_unchecked(): # Setup rng = random.Random(5000) elevators = [ ElevatorHelper(NodeIdentifier.create(f"w{i}", f"a{i}", f"n{i}"), AreaIdentifier(f"w{i}", f"a{i}")) for i in range(6) ] database = tuple(elevators) # Run result = elevator_distributor.two_way_elevator_connections( rng, database, False) # Assert assert result == { NodeIdentifier.create("w0", "a0", "n0"): AreaIdentifier("w4", "a4"), NodeIdentifier.create("w1", "a1", "n1"): AreaIdentifier("w2", "a2"), NodeIdentifier.create("w2", "a2", "n2"): AreaIdentifier("w1", "a1"), NodeIdentifier.create("w3", "a3", "n3"): AreaIdentifier("w5", "a5"), NodeIdentifier.create("w4", "a4", "n4"): AreaIdentifier("w0", "a0"), NodeIdentifier.create("w5", "a5", "n5"): AreaIdentifier("w3", "a3"), }
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 from_json(cls, value: dict) -> "NodeIdentifier": return cls(AreaIdentifier.from_json(value), value["node_name"])
def create(cls, world_name: str, area_name: str, node_name: str) -> "NodeIdentifier": return cls(AreaIdentifier(world_name, area_name), node_name)
def identifier_for_area(self, area: Area) -> AreaIdentifier: world = self.world_with_area(area) return AreaIdentifier(world_name=world.name, area_name=area.name)
def setup_elevators(self): self._elevator_id_to_combo = {} if not hasattr(self.game_configuration, "elevators"): return elevators_config: TeleporterConfiguration = getattr( self.game_configuration, "elevators") world_list = self.game_description.world_list nodes_by_world: Dict[ str, List[TeleporterNode]] = collections.defaultdict(list) areas_to_not_change = { "Sky Temple Gateway", "Sky Temple Energy Controller", "Aerie Transport Station", "Aerie", } targets = {} for world, area, node in world_list.all_worlds_areas_nodes: if isinstance( node, TeleporterNode ) and node.editable and area.name not in areas_to_not_change: name = world.correct_name(area.in_dark_aether) nodes_by_world[name].append(node) location = AreaIdentifier(world.name, area.name) targets[elevators.get_short_elevator_or_area_name( self.game_configuration.game, world_list, location, True)] = location if elevators_config.mode == TeleporterShuffleMode.ONE_WAY_ANYTHING: targets = {} for world in world_list.worlds: for area in world.areas: name = world.correct_name(area.in_dark_aether) targets[f"{name} - {area.name}"] = AreaIdentifier( world.name, area.name) combo_targets = sorted(targets.items(), key=lambda it: it[0]) for world_name in sorted(nodes_by_world.keys()): nodes = nodes_by_world[world_name] nodes_locations = [ world_list.identifier_for_node(node).area_location for node in nodes ] nodes_names = [ elevators.get_short_elevator_or_area_name( self.game_configuration.game, world_list, location, False) for location in nodes_locations ] group = QtWidgets.QGroupBox(self.elevators_scroll_contents) group.setTitle(world_name) self.elevators_scroll_layout.addWidget(group) layout = QtWidgets.QGridLayout(group) for i, (node, location, name) in enumerate( sorted(zip(nodes, nodes_locations, nodes_names), key=lambda it: it[2])): node_name = QtWidgets.QLabel(group) node_name.setText(name) node_name.setWordWrap(True) node_name.setMinimumWidth(75) layout.addWidget(node_name, i, 0) combo = QtWidgets.QComboBox(group) if elevators_config.is_vanilla: combo.addItem("Vanilla", node.default_connection) combo.setEnabled(False) else: combo.addItem("Undefined", None) for target_name, connection in combo_targets: combo.addItem(target_name, connection) combo.setMinimumContentsLength(11) combo.currentIndexChanged.connect( self.update_locations_tree_for_reachable_nodes) self._elevator_id_to_combo[world_list.identifier_for_node( node)] = combo layout.addWidget(combo, i, 1)
def apply_previous_state(self, previous_state: Optional[dict]) -> bool: if previous_state is None: return False starting_location = None needs_starting_location = len( self.game_configuration.starting_location.locations) > 1 configurable_nodes = {} try: pickup_name_to_pickup = { pickup.name: pickup for pickup in self._collected_pickups.keys() } quantity_to_change = { pickup_name_to_pickup[pickup_name]: quantity for pickup_name, quantity in previous_state["collected_pickups"].items() } previous_actions = [ self.game_description.world_list.node_by_identifier( NodeIdentifier.from_string(identifier)) for identifier in previous_state["actions"] ] if needs_starting_location: starting_location = AreaIdentifier.from_json( previous_state["starting_location"]) teleporters: Dict[NodeIdentifier, Optional[AreaIdentifier]] = { NodeIdentifier.from_json(item["teleporter"]): (AreaIdentifier.from_json(item["data"]) if item["data"] is not None else None) for item in previous_state["elevators"] } if self.game_configuration.game == RandovaniaGame.METROID_PRIME_ECHOES: configurable_nodes = { NodeIdentifier.from_string(identifier): (LayoutTranslatorRequirement(item) if item is not None else None) for identifier, item in previous_state["configurable_nodes"].items() } except (KeyError, AttributeError): return False self.setup_starting_location(starting_location) for teleporter, area_location in teleporters.items(): combo = self._elevator_id_to_combo[teleporter] if area_location is None: combo.setCurrentIndex(0) continue for i in range(combo.count()): if area_location == combo.itemData(i): combo.setCurrentIndex(i) break for identifier, requirement in configurable_nodes.items(): combo = self._translator_gate_to_combo[identifier] for i in range(combo.count()): if requirement == combo.itemData(i): combo.setCurrentIndex(i) break self.bulk_change_quantity(quantity_to_change) self._add_new_actions(previous_actions) world_list = self.game_description.world_list state = self.state_for_current_configuration() self.focus_on_world(world_list.nodes_to_world(state.node)) self.focus_on_area(world_list.nodes_to_area(state.node)) return True
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}")
default_echoes_configuration.major_items_configuration, minimum_random_starting_items=2, ), sky_temple_keys=LayoutSkyTempleKeyMode.ALL_BOSSES, ) # Run result = pool_creator.calculate_pool_item_count(layout_configuration) # Assert assert result == (118, 121) @pytest.mark.parametrize("puppies", [False, True]) @pytest.mark.parametrize("starting_area", [ AreaIdentifier("Mimiga Village", "Start Point"), AreaIdentifier("Labyrinth", "Camp") ]) 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,
def node_to_area_location(self, node: Node) -> AreaIdentifier: return AreaIdentifier( world_name=self.nodes_to_world(node).name, area_name=self.nodes_to_area(node).name, )
def ni(w: str, a: str, n: str, tw: str, ta: str): elevator_connection[NodeIdentifier.create(w, a, n)] = AreaIdentifier(tw, ta)