def test_create_base_patches( mock_add_elevator_connections_to_patches: MagicMock, mock_gate_assignment_for_configuration: MagicMock, mock_starting_location_for_config: MagicMock, mock_add_default_hints_to_patches: MagicMock, mocker, ): # Setup rng = MagicMock() game = MagicMock() layout_configuration = MagicMock() layout_configuration.game = RandovaniaGame.PRIME2 mock_replace: MagicMock = mocker.patch("dataclasses.replace") is_multiworld = MagicMock() patches = ([ game.create_game_patches.return_value, mock_replace.return_value, mock_add_elevator_connections_to_patches.return_value, ]) patches.append(patches[-1].assign_gate_assignment.return_value) patches.append(patches[-1].assign_starting_location.return_value) # Run result = base_patches_factory.create_base_patches(layout_configuration, rng, game, is_multiworld, player_index=0) # Assert game.create_game_patches.assert_called_once_with() mock_replace.assert_called_once_with(game.create_game_patches.return_value, game_specific=ANY, player_index=0) mock_add_elevator_connections_to_patches.assert_called_once_with( layout_configuration, rng, patches[1]) # Gate Assignment mock_gate_assignment_for_configuration.assert_called_once_with( layout_configuration, game.resource_database, rng) patches[2].assign_gate_assignment.assert_called_once_with( mock_gate_assignment_for_configuration.return_value) # Starting Location mock_starting_location_for_config.assert_called_once_with( layout_configuration, game, rng) patches[3].assign_starting_location.assert_called_once_with( mock_starting_location_for_config.return_value) # Hints mock_add_default_hints_to_patches.assert_called_once_with( rng, patches[4], game.world_list, num_joke=2, is_multiworld=is_multiworld) assert result is mock_add_default_hints_to_patches.return_value
def run_bootstrap(preset: Preset): game = data_reader.decode_data(preset.configuration.game_data) permalink = Permalink( seed_number=15000, spoiler=True, presets={0: preset}, ) patches = base_patches_factory.create_base_patches(preset.configuration, Random(15000), game, False) _, state = logic_bootstrap(preset.configuration, game, patches) return game, state, permalink
def run_bootstrap(preset: Preset): game = default_database.game_description_for(preset.game) permalink = Permalink( seed_number=15000, spoiler=True, presets={0: preset}, ) patches = base_patches_factory.create_base_patches(preset.configuration, Random(15000), game, False, player_index=0) _, state = logic_bootstrap(preset.configuration, game, patches) return game, state, permalink
def test_create_base_patches( mock_add_game_specific_from_config: MagicMock, mock_add_elevator_connections_to_patches: MagicMock, mock_gate_assignment_for_configuration: MagicMock, mock_starting_location_for_config: MagicMock, mock_add_default_hints_to_patches: MagicMock, ): # Setup rng = MagicMock() game = MagicMock() layout_configuration = MagicMock() patches = [ game.create_game_patches.return_value, mock_add_game_specific_from_config.return_value, mock_add_elevator_connections_to_patches.return_value, ] patches.append(patches[-1].assign_gate_assignment.return_value) patches.append(patches[-1].assign_starting_location.return_value) # Run result = base_patches_factory.create_base_patches(layout_configuration, rng, game) # Assert game.create_game_patches.assert_called_once_with() mock_add_elevator_connections_to_patches.assert_called_once_with( layout_configuration, rng, patches[1]) # Gate Assignment mock_gate_assignment_for_configuration.assert_called_once_with( layout_configuration, game.resource_database, rng) patches[2].assign_gate_assignment.assert_called_once_with( mock_gate_assignment_for_configuration.return_value) # Starting Location mock_starting_location_for_config.assert_called_once_with( layout_configuration, game, rng) patches[3].assign_starting_location.assert_called_once_with( mock_starting_location_for_config.return_value) # Hints mock_add_default_hints_to_patches.assert_called_once_with( rng, patches[4], game.world_list) assert result is mock_add_default_hints_to_patches.return_value
def test_create_base_patches( mock_with_game: MagicMock, mock_add_elevator_connections_to_patches: MagicMock, mock_gate_assignment_for_configuration: MagicMock, mock_starting_location_for_config: MagicMock, mock_add_default_hints_to_patches: MagicMock, ): # Setup rng = MagicMock() game = MagicMock() layout_configuration = MagicMock() first_patches = mock_with_game.return_value second_patches = mock_add_elevator_connections_to_patches.return_value third_patches = second_patches.assign_gate_assignment.return_value fourth_patches = third_patches.assign_starting_location.return_value # Run result = base_patches_factory.create_base_patches(layout_configuration, rng, game) # Assert mock_with_game.assert_called_once_with(game) mock_add_elevator_connections_to_patches.assert_called_once_with( layout_configuration, rng, first_patches) # Gate Assignment mock_gate_assignment_for_configuration.assert_called_once_with( layout_configuration, game.resource_database, rng) second_patches.assign_gate_assignment.assert_called_once_with( mock_gate_assignment_for_configuration.return_value) # Starting Location mock_starting_location_for_config.assert_called_once_with( layout_configuration, game, rng) third_patches.assign_starting_location.assert_called_once_with( mock_starting_location_for_config.return_value) # Hints mock_add_default_hints_to_patches.assert_called_once_with( rng, fourth_patches, game.world_list) assert result is mock_add_default_hints_to_patches.return_value
def create_player_pool(rng: Random, configuration: EchoesConfiguration, player_index: int, num_players: int) -> PlayerPool: game = default_database.game_description_for(configuration.game) base_patches = base_patches_factory.create_base_patches(configuration, rng, game, num_players > 1, player_index=player_index) item_pool, pickup_assignment, initial_items = pool_creator.calculate_pool_results(configuration, game.resource_database) target_assignment = { index: PickupTarget(pickup, player_index) for index, pickup in pickup_assignment.items() } patches = base_patches.assign_pickup_assignment(target_assignment).assign_extra_initial_items(initial_items) return PlayerPool( game=game, configuration=configuration, patches=patches, pickups=item_pool, )
def create_player_pool(rng: Random, configuration: LayoutConfiguration, player_index: int) -> PlayerPool: game = data_reader.decode_data(configuration.game_data) base_patches = dataclasses.replace(base_patches_factory.create_base_patches(configuration, rng, game), player_index=player_index) item_pool, pickup_assignment, initial_items = pool_creator.calculate_pool_results(configuration, game.resource_database) target_assignment = { index: PickupTarget(pickup, player_index) for index, pickup in pickup_assignment.items() } patches = base_patches.assign_pickup_assignment(target_assignment).assign_extra_initial_items(initial_items) return PlayerPool( game=game, configuration=configuration, patches=patches, pickups=item_pool, )
def _retryable_create_patches( configuration: LayoutConfiguration, game: GameDescription, rng: Random, status_update: Callable[[str], None], ) -> Tuple[GamePatches, List[PickupEntry]]: """ Runs the rng-dependant parts of the generation, with retries :param configuration: :param game: :param rng: :param status_update: :return: """ base_patches = base_patches_factory.create_base_patches( configuration, rng, game) pool_patches, item_pool = pool_creator.calculate_item_pool( configuration, game.resource_database, base_patches) _validate_item_pool_size(item_pool, game) return run_filler(configuration, game, item_pool, pool_patches, rng, status_update)
def test_reach_size_from_start_echoes(small_echoes_game_description, default_layout_configuration): # Setup game = small_echoes_game_description specific_levels = { trick.short_name: LayoutTrickLevel.HYPERMODE for trick in game.resource_database.trick } def item(name: str): return find_resource_info_with_long_name(game.resource_database.item, name) def nodes(*names): result = [game.world_list.node_from_name(name) for name in names] result.sort(key=lambda it: it.index) return result layout_configuration = dataclasses.replace( default_layout_configuration, trick_level=TrickLevelConfiguration( minimal_logic=False, specific_levels=specific_levels, game=default_layout_configuration.game), starting_location=LocationList.with_elements( [game.starting_location], game=RandovaniaGame.PRIME2, )) patches = base_patches_factory.create_base_patches(layout_configuration, Random(15000), game, False, player_index=0) state = bootstrap.calculate_starting_state(game, patches) state.resources[item("Combat Visor")] = 1 state.resources[item("Amber Translator")] = 1 state.resources[item("Scan Visor")] = 1 state.resources[item("Morph Ball")] = 1 state.resources[item("Power Beam")] = 1 state.resources[item("Charge Beam")] = 1 state.resources[item("Grapple Beam")] = 1 state.resources[item("Dark Beam")] = 1 state.resources[item("Dark Ammo")] = 50 state.resources[item("Missile")] = 5 # Run reach = GeneratorReach.reach_from_state(game, state) # Assert assert list(reach.nodes) == nodes( "Temple Grounds/Path of Eyes/Front of Translator Gate", "Temple Grounds/Path of Eyes/Lore Scan", "Temple Grounds/Path of Eyes/Translator Gate", "Temple Grounds/Path of Eyes/Door to Torvus Transport Access", "Temple Grounds/Torvus Transport Access/Door to Path of Eyes", "Temple Grounds/Torvus Transport Access/Door to Transport to Torvus Bog", "Temple Grounds/Transport to Torvus Bog/Door to Torvus Transport Access", "Temple Grounds/Transport to Torvus Bog/Elevator to Torvus Bog - Transport to Temple Grounds", "Torvus Bog/Transport to Temple Grounds/Elevator to Temple Grounds - Transport to Torvus Bog", "Torvus Bog/Transport to Temple Grounds/Door to Temple Transport Access", "Torvus Bog/Temple Transport Access/Door to Transport to Temple Grounds", "Torvus Bog/Temple Transport Access/Door to Torvus Lagoon", "Torvus Bog/Torvus Lagoon/Door to Temple Transport Access", "Torvus Bog/Torvus Lagoon/Door to Path of Roots", "Torvus Bog/Torvus Lagoon/Keybearer Corpse (S-Dly)", "Torvus Bog/Path of Roots/Door to Torvus Lagoon", "Torvus Bog/Path of Roots/Door to Great Bridge", "Torvus Bog/Path of Roots/Pickup (Missile)", "Torvus Bog/Path of Roots/Next to Pickup", "Torvus Bog/Path of Roots/Under Lore Scan", "Torvus Bog/Path of Roots/Lore Scan", "Torvus Bog/Great Bridge/Door to Path of Roots", ) assert len(list(reach.safe_nodes)) == 20
def __init__(self, persistence_path: Path, layout_configuration: LayoutConfiguration): super().__init__() self.setupUi(self) set_default_window_icon(self) self.menu_reset_action = QAction("Reset", self) self.menu_reset_action.triggered.connect(self._confirm_reset) self.menu_bar.addAction(self.menu_reset_action) self._collected_pickups = {} self._widget_for_pickup = {} self._actions = [] self._asset_id_to_item = {} self._node_to_item = {} self.layout_configuration = layout_configuration self.persistence_path = persistence_path self.game_description = data_reader.decode_data( layout_configuration.game_data) try: base_patches = base_patches_factory.create_base_patches( self.layout_configuration, None, self.game_description) except base_patches_factory.MissingRng as e: raise InvalidLayoutForTracker( "Layout is configured to have random {}, " "but that isn't supported by the tracker.".format(e)) pool_patches, item_pool = pool_creator.calculate_item_pool( self.layout_configuration, self.game_description.resource_database, base_patches) self.game_description, self._initial_state = logic_bootstrap( layout_configuration, self.game_description, pool_patches) self.logic = Logic(self.game_description, layout_configuration) self._initial_state.resources[ "add_self_as_requirement_to_resources"] = 1 self.resource_filter_check.stateChanged.connect( self.update_locations_tree_for_reachable_nodes) self.hide_collected_resources_check.stateChanged.connect( self.update_locations_tree_for_reachable_nodes) self.undo_last_action_button.clicked.connect(self._undo_last_action) self.configuration_label.setText( "Trick Level: {}; Elevators: Vanilla; Starts with:\n{}".format( layout_configuration.trick_level_configuration.global_level. value, ", ".join(resource.short_name for resource in pool_patches.starting_items.keys()))) self.setup_pickups_box(item_pool) self.setup_possible_locations_tree() self._starting_nodes = { node for node in self.game_description.world_list.all_nodes if node.is_resource_node and node.resource() in self._initial_state.resources } persistence_path.mkdir(parents=True, exist_ok=True) previous_state = _load_previous_state(persistence_path, layout_configuration) if not self.apply_previous_state(previous_state): with persistence_path.joinpath("layout_configuration.json").open( "w") as layout_file: json.dump(layout_configuration.as_json, layout_file) self._add_new_action(self._initial_state.node)