def test_prevent_redundant(): res_a, id_req_a = make_req_a() res_b, id_req_b = make_req_b() the_set = RequirementSet([ RequirementList(0, [id_req_a]), RequirementList(0, [id_req_a, id_req_b]), ]) assert the_set.alternatives == frozenset([RequirementList(0, [id_req_a])])
def test_requirement_as_set_1(): req = RequirementAnd([ _req("A"), RequirementOr([_req("B"), _req("C")]), RequirementOr([_req("D"), _req("E")]), ]) assert req.as_set(None) == RequirementSet([ RequirementList([_req("A"), _req("B"), _req("D")]), RequirementList([_req("A"), _req("B"), _req("E")]), RequirementList([_req("A"), _req("C"), _req("D")]), RequirementList([_req("A"), _req("C"), _req("E")]), ])
def test_set_as_str_things(echoes_resource_database): item = echoes_resource_database.get_item_by_name req_set = RequirementSet([ RequirementList([ ResourceRequirement(item("Screw Attack"), 1, False), ResourceRequirement(item("Space Jump Boots"), 1, False), ]), RequirementList([ ResourceRequirement(item("Power Bomb"), 1, False), ]), ]) assert req_set.as_str == "(Power Bomb ≥ 1) or (Screw Attack ≥ 1, Space Jump Boots ≥ 1)"
def test_simplify_requirement_set_static(): res_a, id_req_a = make_req_a() res_b, id_req_b = make_req_b() the_set = RequirementSet([ RequirementList(0, [id_req_a]), RequirementList(0, [id_req_b]), ]) simple_1 = the_set.simplify({res_a: 0, res_b: 0}) simple_2 = the_set.simplify({res_a: 0, res_b: 1}) simple_3 = the_set.simplify({res_a: 1, res_b: 1}) assert simple_1.alternatives == frozenset() assert simple_2.alternatives == frozenset([RequirementList(0, [])]) assert simple_3.alternatives == frozenset([RequirementList(0, [])])
def requirements_to_leave(self, patches: GamePatches, current_resources: CurrentResources) -> RequirementSet: return RequirementSet([ RequirementList(0, [ IndividualRequirement(patches.translator_gates[self.gate], 1, False), IndividualRequirement(self.scan_visor, 1, False), ]) ])
def test_simplify_requirement_set_static(): res_a, id_req_a = make_req_a() res_b, id_req_b = make_req_b() the_set = RequirementOr([ RequirementAnd([id_req_a]), RequirementAnd([id_req_b]), ]) simple_1 = the_set.patch_requirements({res_a: 0, res_b: 0}, 1) simple_2 = the_set.patch_requirements({res_a: 0, res_b: 1}, 1) simple_3 = the_set.patch_requirements({res_a: 1, res_b: 1}, 1) assert simple_1.as_set.alternatives == frozenset() assert simple_2.as_set.alternatives == frozenset([RequirementList([])]) assert simple_3.as_set.alternatives == frozenset([RequirementList([])])
def test_requirement_template_nested(database): # Setup use_a = RequirementTemplate(database, "Use A") use_b = RequirementTemplate(database, "Use B") database.requirement_template["Use A"] = _req("A") database.requirement_template["Use B"] = RequirementOr([use_a, _req("B")]) # Run as_set = use_b.as_set # Assert assert as_set == RequirementSet([ RequirementList([_req("A")]), RequirementList([_req("B")]), ])
def test_requirement_as_set_3(): req = RequirementOr([ Requirement.impossible(), _req("A"), ]) assert req.as_set(None) == RequirementSet([ RequirementList([_req("A")]), ])
def test_requirement_as_set_2(): req = RequirementAnd([ Requirement.trivial(), _req("A"), ]) assert req.as_set(None) == RequirementSet([ RequirementList([_req("A")]), ])
def requirements_to_leave( self, patches: GamePatches, current_resources: CurrentResources) -> RequirementSet: return RequirementSet([ RequirementList(0, [ IndividualRequirement(self.pickup_node.pickup_index, 1, False), ]) ])
def test_get_pickups_that_solves_unreachable(echoes_game_description, mocker): def item(name): return search.find_resource_info_with_long_name( echoes_game_description.resource_database.item, name) mock_req_lists: MagicMock = mocker.patch( "randovania.generator.filler.pickup_list._requirement_lists_without_satisfied_resources" ) pickups_left = [] reach = MagicMock() reach.state.resources = {} reach.state.energy = 100 possible_set = MagicMock() reach.unreachable_nodes_with_requirements.return_value = { "foo": possible_set } uncollected_resource_nodes = [MagicMock()] mock_req_lists.return_value = { RequirementList([ ResourceRequirement(item("Dark Visor"), 1, False), ResourceRequirement(item("Missile"), 5, False), ]), RequirementList([ ResourceRequirement(item("Screw Attack"), 1, False), ]), RequirementList([ ResourceRequirement(item("Power Bomb"), 1, False), ResourceRequirement(item("Boost Ball"), 1, False), ]), RequirementList([ ResourceRequirement(item("Spider Ball"), 1, False), ResourceRequirement(item("Boost Ball"), 1, False), ]), } # Run result = pickup_list.get_pickups_that_solves_unreachable( pickups_left, reach, uncollected_resource_nodes) # Assert mock_req_lists.assert_called_once_with( reach.state, [possible_set], [uncollected_resource_nodes[0].resource.return_value]) assert result == tuple()
def requirements_to_leave(self, patches: GamePatches, current_resources: CurrentResources) -> RequirementSet: if current_resources.get("add_self_as_requirement_to_resources") == 1: return RequirementSet([ RequirementList(0, [ IndividualRequirement(self.event, 1, False), ]) ]) else: return RequirementSet.trivial()
def test_requirement_as_set_5(): req = RequirementAnd([ _req("A"), _req("B"), _req("C"), ]) assert req.as_set == RequirementSet([ RequirementList([_req("A"), _req("B"), _req("C")]), ])
def test_requirement_as_set_4(): req = RequirementOr([ Requirement.impossible(), _req("A"), Requirement.trivial(), ]) assert req.as_set == RequirementSet([ RequirementList([]), ])
def requirements_to_leave( self, patches: GamePatches, current_resources: CurrentResources) -> RequirementSet: items = [IndividualRequirement(self.scan_visor, 1, False)] if self.required_translator is not None: items.append( IndividualRequirement(self.required_translator, 1, False)) return RequirementSet([RequirementList(0, items)])
def requirements_to_leave(self, patches: GamePatches, current_resources: CurrentResources) -> RequirementSet: # FIXME: using non-resource as key in CurrentResources if current_resources.get("add_self_as_requirement_to_resources") == 1: return RequirementSet([ RequirementList(0, [ IndividualRequirement(self.pickup_index, 1, False), ]) ]) else: return RequirementSet.trivial()
def test_list_dangerous_resources(input_data, output_data): # setup req_list = RequirementList( (ResourceRequirement(_make_resource(str(item[0])), 1, item[1]) for item in input_data)) expected_result = {_make_resource(str(item)) for item in output_data} # run result = set(req_list.dangerous_resources) # assert assert result == expected_result
def test_requirement_set_constructor(echoes_resource_database): item = echoes_resource_database.get_item_by_name req_set = RequirementSet([ RequirementList([ ResourceRequirement(item("Dark Visor"), 1, False), ResourceRequirement(item("Missile"), 5, False), ResourceRequirement(item("Seeker Launcher"), 1, False), ]), RequirementList([ ResourceRequirement(item("Screw Attack"), 1, False), ResourceRequirement(item("Space Jump Boots"), 1, False), ]), RequirementList([ ResourceRequirement(item("Power Bomb"), 1, False), ResourceRequirement(item("Boost Ball"), 1, False), ]), ]) extract = [ sorted((req.resource.long_name, req.amount) for req in req_list.items) for req_list in req_set.alternatives ] assert sorted(extract) == [ [ ("Boost Ball", 1), ("Power Bomb", 1), ], [ ("Dark Visor", 1), ("Missile", 5), ("Seeker Launcher", 1), ], [ ("Screw Attack", 1), ("Space Jump Boots", 1), ], ]
def _simplify_requirement_list(self: RequirementList, state: State) -> Optional[RequirementList]: items = [] for item in self.values(): if item.negate: return None if item.satisfied(state.resources, state.resource_database): continue if not isinstance(item.resource, PickupIndex): # An empty RequirementList is considered satisfied, so we don't have to add the trivial resource items.append(item) return RequirementList(self.difficulty_level, items)
def test_minimum_satisfied_difficulty(database: ResourceDatabase, resources, expected_level): res_a, id_req_a = make_req_a() res_b, id_req_b = make_req_b() res_c, id_req_c = make_req_c() the_set = RequirementSet([ RequirementList(0, [id_req_a]), RequirementList(1, [ id_req_b, IndividualRequirement(database.difficulty_resource, 1, False) ]), RequirementList(2, [ id_req_c, IndividualRequirement(database.difficulty_resource, 2, False) ]), ]) res = { database.get_by_type_and_index(ResourceType.ITEM, x): 1 for x in resources } res[database.difficulty_resource] = 10 diff = the_set.minimum_satisfied_difficulty(res, 99) assert diff == expected_level
def test_list_dangerous_resources(input_data, output_data): # setup req_list = RequirementList(0, (IndividualRequirement( SimpleResourceInfo(item[0], str(item[0]), str(item[0]), ""), 1, item[1]) for item in input_data)) expected_result = { SimpleResourceInfo(item, str(item), str(item), "") for item in output_data } # run result = set(req_list.dangerous_resources) # assert assert result == expected_result
def test_set_hash(echoes_resource_database): req_set_a = RequirementSet([ RequirementList([ ResourceRequirement( echoes_resource_database.get_item_by_name("Power Bomb"), 1, False), ]), ]) req_set_b = RequirementSet([ RequirementList([ ResourceRequirement( echoes_resource_database.get_item_by_name("Power Bomb"), 1, False), ]), ]) assert req_set_a == req_set_b assert req_set_a is not req_set_b hash_a = hash(req_set_a) hash_b = hash(req_set_b) assert hash_a == hash_b assert hash_a == req_set_a._cached_hash
def test_trivial_merge(): trivial = RequirementSet.trivial() impossible = RequirementSet.impossible() res_a, id_req_a = make_req_a() the_set = RequirementSet([ RequirementList(0, [id_req_a]), ]) assert trivial.union(trivial) == trivial assert trivial.union(the_set) == the_set assert the_set.union(trivial) == the_set assert trivial.union(impossible) == impossible assert impossible.union(the_set) == impossible assert the_set.union(impossible) == impossible assert the_set.union(the_set) == the_set
def _simplify_requirement_list(self: RequirementList, state: State, dangerous_resources: FrozenSet[ResourceInfo], ) -> Optional[RequirementList]: items = [] for item in self.values(): if item.negate: return None if item.satisfied(state.resources, state.energy): continue if item.resource not in dangerous_resources: # An empty RequirementList is considered satisfied, so we don't have to add the trivial resource items.append(item) return RequirementList(items)
def test_requirement_list_constructor(echoes_resource_database): def item(name): return search.find_resource_info_with_long_name( echoes_resource_database.item, name) req_list = RequirementList([ ResourceRequirement(item("Dark Visor"), 1, False), ResourceRequirement(item("Missile"), 5, False), ResourceRequirement(item("Seeker Launcher"), 1, False), ]) extract = [(req.resource.long_name, req.amount) for req in req_list.items] assert sorted(extract) == [ ("Dark Visor", 1), ("Missile", 5), ("Seeker Launcher", 1), ]
def test_requirement_lists_without_satisfied_resources(echoes_game_description, default_echoes_preset, echoes_game_patches): # Setup def item(name): return search.find_resource_info_with_long_name( echoes_game_description.resource_database.item, name) state = echoes_game_description.game.generator.bootstrap.calculate_starting_state( echoes_game_description, echoes_game_patches, default_echoes_preset.configuration) state.resources[item("Seeker Launcher")] = 1 state.resources[item("Space Jump Boots")] = 1 uncollected_resources = [] possible_sets = [ RequirementSet([ RequirementList([ ResourceRequirement(item("Dark Visor"), 1, False), ResourceRequirement(item("Missile"), 5, False), ResourceRequirement(item("Seeker Launcher"), 1, False), ]), RequirementList([ ResourceRequirement(item("Screw Attack"), 1, False), ResourceRequirement(item("Space Jump Boots"), 1, False), ]), RequirementList([ ResourceRequirement(item("Power Bomb"), 1, False), ResourceRequirement(item("Boost Ball"), 1, False), ]), ]), RequirementSet([ RequirementList([ ResourceRequirement(item("Power Bomb"), 1, False), ResourceRequirement(item("Boost Ball"), 1, False), ]), RequirementList([ ResourceRequirement(item("Spider Ball"), 1, False), ResourceRequirement(item("Boost Ball"), 1, False), ]), ]), ] # Run result = pickup_list._requirement_lists_without_satisfied_resources( state, possible_sets, uncollected_resources) # Assert assert result == { RequirementList([ ResourceRequirement(item("Dark Visor"), 1, False), ResourceRequirement(item("Missile"), 5, False), ]), RequirementList([ ResourceRequirement(item("Screw Attack"), 1, False), ]), RequirementList([ ResourceRequirement(item("Power Bomb"), 1, False), ResourceRequirement(item("Boost Ball"), 1, False), ]), RequirementList([ ResourceRequirement(item("Spider Ball"), 1, False), ResourceRequirement(item("Boost Ball"), 1, False), ]), }
def test_empty_requirement_list(): assert RequirementList(0, []).satisfied({}, 99)
def make_single_set( id_req: Tuple[SimpleResourceInfo, IndividualRequirement]) -> RequirementSet: return RequirementSet([RequirementList(0, [id_req[1]])])
RequirementList(0, [id_req_a]), ]) assert trivial.union(trivial) == trivial assert trivial.union(the_set) == the_set assert the_set.union(trivial) == the_set assert trivial.union(impossible) == impossible assert impossible.union(the_set) == impossible assert the_set.union(impossible) == impossible assert the_set.union(the_set) == the_set @pytest.mark.parametrize("replacement", [ RequirementSet.impossible(), make_single_set(make_req_a()), RequirementSet([RequirementList( 0, [make_req_a()[1], make_req_b()[1]])]), ]) def test_replace_missing(replacement): trivial = RequirementSet.trivial() req_a = SimpleResourceInfo(0, "A", "A", "") id_req_a = IndividualRequirement(req_a, 1, False) result = trivial.replace(id_req_a, replacement) assert result == trivial @pytest.mark.parametrize(["a", "b", "expected"], [ (RequirementSet.impossible(), make_single_set( make_req_a()), make_single_set(make_req_a())),
def test_empty_requirement_list_satisfied(): assert RequirementList([]).satisfied({}, 99, None)