def test_add_pickup_to_state(state_game_data, empty_patches, generic_item_category): # Starting State s = state.State({}, (), 99, None, empty_patches, None, state_game_data) resource_a = ItemResourceInfo("A", "A", 10) resource_b = ItemResourceInfo("B", "B", 10) p = PickupEntry("B", 2, generic_item_category, generic_item_category, progression=( (resource_a, 1), (resource_b, 1), )) # Run state.add_pickup_to_state(s, p) state.add_pickup_to_state(s, p) # Assert assert s.resources == { resource_a: 1, resource_b: 1, }
def test_add_pickup_to_state(state_game_data, empty_patches, generic_item_category): # Starting State db = state_game_data.resource_database starting_node = state_game_data.world_list.resolve_teleporter_connection( empty_patches.game.starting_location) s = state.State(ResourceCollection(), (), 99, starting_node, empty_patches, None, state_game_data) resource_a = db.item[0] resource_b = db.item[1] p = PickupEntry("B", 2, generic_item_category, generic_item_category, progression=( (resource_a, 1), (resource_b, 1), )) # Run state.add_pickup_to_state(s, p) state.add_pickup_to_state(s, p) # Assert assert s.resources == ResourceCollection.from_dict(db, { resource_a: 1, resource_b: 1, })
def test_database_collectable(preset_manager, game_enum: RandovaniaGame, ignore_events: set[str], ignore_pickups: set[int]): game, initial_state, permalink = run_bootstrap( preset_manager.default_preset_for_game(game_enum).get_preset()) all_pickups = set( reach_lib.filter_pickup_nodes(game.world_list.iterate_nodes())) pool_results = pool_creator.calculate_pool_results( permalink.get_preset(0).configuration, game.resource_database) initial_state.resources.add_resource_gain( pool_results.initial_resources.as_resource_gain()) for pickup in pool_results.pickups: add_pickup_to_state(initial_state, pickup) for pickup in pool_results.assignment.values(): add_pickup_to_state(initial_state, pickup) for trick in game.resource_database.trick: initial_state.resources.set_resource( trick, LayoutTrickLevel.maximum().as_number) expected_events = sorted([ event for event in game.resource_database.event if event.short_name not in ignore_events ], key=lambda it: it.short_name) expected_pickups = sorted(it.pickup_index for it in all_pickups if it.pickup_index.index not in ignore_pickups) reach = _create_reach_with_unsafe(game, initial_state.heal()) while list(reach_lib.collectable_resource_nodes(reach.nodes, reach)): reach.act_on( next(iter(reach_lib.collectable_resource_nodes(reach.nodes, reach)))) reach = advance_reach_with_possible_unsafe_resources(reach) # print("\nCurrent reach:") # print(game.world_list.node_name(reach.state.node, with_world=True)) # for world in game.world_list.worlds: # print(f"\n>> {world.name}") # for node in world.all_nodes: # print("[{!s:>5}, {!s:>5}, {!s:>5}] {}".format( # reach.is_reachable_node(node), reach.is_safe_node(node), # reach.state.resources.get(node.resource(), 0) > 0 # if isinstance(node, ResourceNode) else "", # game.world_list.node_name(node, with_world=True))) collected_indices = set(reach.state.collected_pickup_indices) collected_events = { resource for resource, quantity in reach.state.resources.as_resource_gain() if quantity > 0 and resource.resource_type == ResourceType.EVENT } assert list(reach_lib.collectable_resource_nodes(reach.nodes, reach)) == [] assert sorted(collected_indices) == expected_pickups assert sorted(collected_events, key=lambda it: it.short_name) == expected_events
def state_for_current_configuration(self) -> Optional[State]: state = self._initial_state.copy() state.node = self._actions[-1] for pickup, quantity in self._collected_pickups.items(): for _ in range(quantity): add_pickup_to_state(state, pickup) for node in self._collected_nodes: add_resource_gain_to_current_resources(node.resource_gain_on_collect(state.patches, state.resources), state.resources) return state
def test_database_collectable(preset_manager, preset_name, ignore_events, ignore_pickups): game, initial_state, permalink = run_bootstrap( preset_manager.preset_for_name(preset_name).get_preset()) all_pickups = set(filter_pickup_nodes(game.world_list.all_nodes)) pool_results = pool_creator.calculate_pool_results( permalink.get_preset(0).configuration, game.resource_database) add_resources_into_another(initial_state.resources, pool_results.initial_resources) for pickup in pool_results.pickups: add_pickup_to_state(initial_state, pickup) for pickup in pool_results.assignment.values(): add_pickup_to_state(initial_state, pickup) for trick in game.resource_database.trick: initial_state.resources[trick] = LayoutTrickLevel.HYPERMODE.as_number expected_events = [ event for event in game.resource_database.event if event.index not in ignore_events ] expected_pickups = sorted(it.pickup_index for it in all_pickups if it.pickup_index.index not in ignore_pickups) reach = _create_reach_with_unsafe(game, initial_state.heal()) while list(collectable_resource_nodes(reach.nodes, reach)): reach.act_on(next(iter(collectable_resource_nodes(reach.nodes, reach)))) reach = advance_reach_with_possible_unsafe_resources(reach) # print("\nCurrent reach:") # for world in game.world_list.worlds: # print(f"\n>> {world.name}") # for node in world.all_nodes: # print("[{!s:>5}, {!s:>5}, {!s:>5}] {}".format( # reach.is_reachable_node(node), reach.is_safe_node(node), # reach.state.resources.get(node.resource(), 0) > 0 if isinstance(node, ResourceNode) else "", # game.world_list.node_name(node))) collected_indices = { resource for resource, quantity in reach.state.resources.items() if quantity > 0 and isinstance(resource, PickupIndex) } collected_events = { resource for resource, quantity in reach.state.resources.items() if quantity > 0 and resource.resource_type == ResourceType.EVENT } assert list(collectable_resource_nodes(reach.nodes, reach)) == [] assert sorted(collected_indices) == expected_pickups assert sorted(collected_events, key=lambda it: it.index) == expected_events
def test_calculate_reach_with_all_pickups(test_data): game, state, _ = test_data item_pool = calculate_item_pool(LayoutConfiguration.from_params(), game.resource_database, state.patches) add_resources_into_another(state.resources, item_pool[0].starting_items) for pickup in item_pool[1]: add_pickup_to_state(state, pickup) first_reach, second_reach = _create_reaches_and_compare(game, state) first_actions, second_actions = _compare_actions(first_reach, second_reach) found_pickups = set( filter_pickup_nodes(filter_reachable(second_reach.nodes, first_reach))) all_pickups = set(filter_pickup_nodes(game.world_list.all_nodes)) # assert (len(list(first_reach.nodes)), len(first_actions)) == (898, 9) # assert (len(list(second_reach.nodes)), len(second_actions)) == (898, 9) pprint.pprint(first_actions) assert all_pickups == found_pickups
def test_add_pickup_to_state(database, patches): # Starting State s = state.State({}, (), 99, None, patches, None, database, None) resource_a = ItemResourceInfo(1, "A", "A", 10, None) resource_b = ItemResourceInfo(2, "B", "B", 10, None) p = PickupEntry("B", 2, ItemCategory.SUIT, ItemCategory.LIFE_SUPPORT, ( ConditionalResources(None, None, ((resource_a, 1), )), ConditionalResources(None, resource_a, ((resource_b, 1), )), )) # Run state.add_pickup_to_state(s, p) state.add_pickup_to_state(s, p) # Assert assert s.resources == { resource_a: 1, resource_b: 1, }
def test_add_pickup_to_state(database): # Starting State s = state.State({}, (), 99, None, None, None, database) resource_a = SimpleResourceInfo(1, "A", "A", ResourceType.ITEM) resource_b = SimpleResourceInfo(2, "B", "B", ResourceType.ITEM) p = PickupEntry("B", 2, ItemCategory.SUIT, ( ConditionalResources(None, None, ((resource_a, 1), )), ConditionalResources(None, resource_a, ((resource_b, 1), )), )) # Run state.add_pickup_to_state(s, p) state.add_pickup_to_state(s, p) # Assert assert s.resources == { resource_a: 1, resource_b: 1, }
def test_calculate_reach_with_all_pickups(test_data): game, state, permalink = test_data pool_results = pool_creator.calculate_pool_results( permalink.get_preset(0).layout_configuration, game.resource_database) add_resources_into_another(state.resources, pool_results.initial_resources) for pickup in pool_results.pickups: add_pickup_to_state(state, pickup) for pickup in pool_results.assignment.values(): add_pickup_to_state(state, pickup) first_reach, second_reach = _create_reaches_and_compare(game, state) first_actions, second_actions = _compare_actions(first_reach, second_reach) found_pickups = set( filter_pickup_nodes(filter_reachable(second_reach.nodes, first_reach))) all_pickups = set(filter_pickup_nodes(game.world_list.all_nodes)) # assert (len(list(first_reach.nodes)), len(first_actions)) == (898, 9) # assert (len(list(second_reach.nodes)), len(second_actions)) == (898, 9) pprint.pprint(first_actions) assert all_pickups == found_pickups
def state_for_current_configuration(self) -> Optional[State]: state = self._initial_state.copy() if self._actions: state.node = self._actions[-1] for teleporter, combo in self._elevator_id_to_combo.items(): assert combo.currentData() is not None state.patches.elevator_connection[teleporter] = combo.currentData() for gate, item in self._translator_gate_to_combo.items(): state.patches.translator_gates[gate] = item.currentData() for pickup, quantity in self._collected_pickups.items(): for _ in range(quantity): add_pickup_to_state(state, pickup) for node in self._collected_nodes: add_resource_gain_to_current_resources( node.resource_gain_on_collect(state.patches, state.resources), state.resources) return state
def state_for_current_configuration(self) -> Optional[State]: state = self._initial_state.copy() if self._actions: state.node = self._actions[-1] state.patches = state.patches.assign_elevators( (state.world_list.get_teleporter_node(teleporter), combo.currentData()) for teleporter, combo in self._elevator_id_to_combo.items()) for gate, item in self._translator_gate_to_combo.items(): scan_visor = self.game_description.resource_database.get_item( "Scan") requirement: Optional[ LayoutTranslatorRequirement] = item.currentData() if requirement is None: translator_req = Requirement.impossible() else: translator = self.game_description.resource_database.get_item( requirement.item_name) translator_req = ResourceRequirement.simple(translator) state.patches.configurable_nodes[gate] = RequirementAnd([ ResourceRequirement.simple(scan_visor), translator_req, ]) for pickup, quantity in self._collected_pickups.items(): for _ in range(quantity): add_pickup_to_state(state, pickup) for node in self._collected_nodes: state.resources.add_resource_gain( node.resource_gain_on_collect(state.node_context())) return state
def test_add_pickup_to_state(state_game_data, empty_patches): # Starting State s = state.State({}, (), 99, None, empty_patches, None, state_game_data) resource_a = ItemResourceInfo(1, "A", "A", 10, None) resource_b = ItemResourceInfo(2, "B", "B", 10, None) p = PickupEntry("B", 2, ItemCategory.SUIT, ItemCategory.LIFE_SUPPORT, progression=( (resource_a, 1), (resource_b, 1), )) # Run state.add_pickup_to_state(s, p) state.add_pickup_to_state(s, p) # Assert assert s.resources == { resource_a: 1, resource_b: 1, }
def random_assumed_filler( logic: Logic, initial_state: State, patches: GamePatches, available_pickups: Tuple[PickupEntry], rng: Random, status_update: Callable[[str], None], ) -> PickupAssignment: pickup_assignment = copy.copy(patches.pickup_assignment) print("Major items: {}".format([item.name for item in available_pickups])) game = logic.game base_reach = advance_reach_with_possible_unsafe_resources( reach_with_all_safe_resources(game, initial_state)) reaches_for_pickup = {} previous_reach = base_reach for pickup in reversed(available_pickups): print("** Preparing reach for {}".format(pickup.name)) new_reach = copy.deepcopy(previous_reach) add_pickup_to_state(new_reach.state, pickup) new_reach.state.previous_state = new_reach.state new_reach.advance_to(new_reach.state) collect_all_safe_resources_in_reach(new_reach) previous_reach = advance_reach_with_possible_unsafe_resources( new_reach) reaches_for_pickup[pickup] = previous_reach for i, pickup in enumerate(available_pickups): print("\n\n\nWill place {}, have {} pickups left".format( pickup, len(available_pickups) - i - 1)) reach = reaches_for_pickup[pickup] debug.print_actions_of_reach(reach) escape_state = state_with_pickup(reach.state, pickup) total_pickup_nodes = list( _filter_pickups(filter_reachable(reach.nodes, reach))) pickup_nodes = list( filter_unassigned_pickup_nodes(total_pickup_nodes, pickup_assignment)) num_nodes = len(pickup_nodes) actions_weights = { node: len(path) for node, path in reach.shortest_path_from( initial_state.node).items() } try: pickup_node = next( pickup_nodes_that_can_reach( iterate_with_weights(pickup_nodes, actions_weights, rng), reach_with_all_safe_resources(game, escape_state), set(reach.safe_nodes))) print("Placed {} at {}. Had {} available of {} nodes.".format( pickup.name, game.world_list.node_name(pickup_node, True), num_nodes, len(total_pickup_nodes))) except StopIteration: print("\n".join( game.world_list.node_name(node, True) for node in reach.safe_nodes)) raise Exception( "Couldn't place {}. Had {} available of {} nodes.".format( pickup.name, num_nodes, len(total_pickup_nodes))) pickup_assignment[pickup_node.pickup_index] = pickup return pickup_assignment