Exemplo n.º 1
0
def print_retcon_loop_start(game: GameDescription,
                            pickups_left: Iterator[PickupEntry],
                            reach: GeneratorReach,
                            player_index: int,
                            ):
    if debug.debug_level() > 0:
        current_uncollected = UncollectedState.from_reach(reach)
        if debug.debug_level() > 1:
            extra = ", pickups_left: {}".format(sorted(set(pickup.name for pickup in pickups_left)))
        else:
            extra = ""

        print("\n\n===============================")
        print("\n>>> Player {}: From {}, {} open pickup indices, {} open resources{}".format(
            player_index,
            game.world_list.node_name(reach.state.node, with_world=True),
            len(current_uncollected.indices),
            len(current_uncollected.resources),
            extra
        ))

        if debug.debug_level() > 2:
            print("\nCurrent reach:")
            for node in reach.nodes:
                print("[{!s:>5}, {!s:>5}] {}".format(reach.is_reachable_node(node), reach.is_safe_node(node),
                                                     game.world_list.node_name(node)))
Exemplo n.º 2
0
def get_pickups_that_solves_unreachable(
    pickups_left: List[PickupEntry],
    reach: GeneratorReach,
    uncollected_resource_nodes: List[ResourceNode],
) -> PickupCombinations:
    """New logic. Given pickup list and a reach, checks the combination of pickups
    that satisfies on unreachable nodes"""
    state = reach.state
    possible_sets = list(reach.unreachable_nodes_with_requirements().values())
    context = reach.node_context()
    uncollected_resources = [
        node.resource(context) for node in uncollected_resource_nodes
    ]

    all_lists = _requirement_lists_without_satisfied_resources(
        state, possible_sets, uncollected_resources)

    result = []
    for requirement_list in sorted(all_lists,
                                   key=lambda it: it.as_stable_sort_tuple):
        pickups = pickups_to_solve_list(pickups_left, requirement_list, state)
        if pickups is not None and pickups:
            # FIXME: avoid duplicates in result
            result.append(tuple(pickups))

    if debug.debug_level() > 2:
        print(">> All pickup combinations alternatives:")
        for items in sorted(result):
            print("* {}".format(", ".join(p.name for p in items)))

    return tuple(result)
Exemplo n.º 3
0
def collect_all_safe_resources_in_reach(reach: GeneratorReach) -> None:
    """

    :param reach:
    :return:
    """
    while True:
        actions = list(_get_safe_resources(reach))
        if not actions:
            break

        for action in actions:
            if action.can_collect(reach.node_context()):
                # assert reach.is_safe_node(action)
                reach.advance_to(reach.state.act_on_node(action), is_safe=True)
Exemplo n.º 4
0
def test_reach_size_from_start(echoes_game_description,
                               default_layout_configuration, minimal_logic,
                               nodes, safe_nodes):
    # Setup
    specific_levels = {
        trick.short_name: LayoutTrickLevel.HYPERMODE
        for trick in echoes_game_description.resource_database.trick
    }

    layout_configuration = dataclasses.replace(
        default_layout_configuration,
        trick_level_configuration=TrickLevelConfiguration(
            minimal_logic=minimal_logic,
            specific_levels=specific_levels if not minimal_logic else {}),
    )
    player_pool = generator.create_player_pool(Random(15000),
                                               layout_configuration, 0)

    game, state = logic_bootstrap(layout_configuration, player_pool.game,
                                  player_pool.patches)

    # Run
    reach = GeneratorReach.reach_from_state(game, state)

    # Assert
    assert len(list(reach.nodes)) >= nodes
    assert len(list(reach.safe_nodes)) >= safe_nodes
Exemplo n.º 5
0
def interesting_resources_for_reach(
        reach: GeneratorReach) -> FrozenSet[ResourceInfo]:
    satisfiable_requirements: FrozenSet[RequirementList] = frozenset(
        itertools.chain.from_iterable(
            requirements.alternatives for requirements in
            reach.unreachable_nodes_with_requirements().values()))
    return game_description.calculate_interesting_resources(
        satisfiable_requirements, reach.state.resources, reach.state.energy,
        reach.state.resource_database)
Exemplo n.º 6
0
def print_actions_of_reach(reach: GeneratorReach):
    if _DEBUG_LEVEL <= 1:
        return

    game = reach.game
    actions = get_collectable_resource_nodes_of_reach(reach)

    for action in actions:
        print("++ Safe? {1} -- {0} -- Dangerous? {2}".format(
            game.world_list.node_name(action), reach.is_safe_node(action),
            action.resource() in game.dangerous_resources))
Exemplo n.º 7
0
def print_new_resources(
    game: GameDescription,
    reach: GeneratorReach,
    seen_count: dict[ResourceInfo, int],
    label: str,
):
    if debug.debug_level() > 1:
        world_list = game.world_list
        for index, count in seen_count.items():
            if count == 1:
                node = find_node_with_resource(index, reach.node_context(),
                                               world_list.iterate_nodes())
                print("-> New {}: {}".format(
                    label, world_list.node_name(node, with_world=True)))
Exemplo n.º 8
0
def _calculate_weights_for(
    potential_reach: GeneratorReach,
    current_uncollected: UncollectedState,
) -> float:
    if potential_reach.victory_condition_satisfied():
        return _VICTORY_WEIGHT

    potential_uncollected = UncollectedState.from_reach(
        potential_reach) - current_uncollected
    return sum((
        _EVENTS_WEIGHT_MULTIPLIER * int(bool(potential_uncollected.events)),
        _INDICES_WEIGHT_MULTIPLIER * int(bool(potential_uncollected.indices)),
        _LOGBOOKS_WEIGHT_MULTIPLIER *
        int(bool(potential_uncollected.logbooks)),
    ))
Exemplo n.º 9
0
def print_new_resources(game: GameDescription,
                        reach: GeneratorReach,
                        seen_count: Dict[ResourceInfo, int],
                        label: str,
                        ):
    world_list = game.world_list
    if debug.debug_level() > 1:
        for index, count in seen_count.items():
            if count == 1:
                node = find_node_with_resource(index, world_list.all_nodes)
                print("-> New {}: {}".format(label, world_list.node_name(node, with_world=True)))

                if debug.debug_level() > 2:
                    paths = reach.shortest_path_from(node)
                    path = paths.get(reach.state.node, [])
                    print([node.name for node in path])
        print("")
Exemplo n.º 10
0
def test_reach_size_from_start(echoes_game_description):
    # Setup
    configuration = LayoutConfiguration.from_params(
        trick_level_configuration=TrickLevelConfiguration(
            LayoutTrickLevel.HYPERMODE), )
    patches = GamePatches.with_game(echoes_game_description)
    patches = patches.assign_gate_assignment(
        base_patches_factory.gate_assignment_for_configuration(
            configuration, echoes_game_description.resource_database,
            Random(15000)))

    game, state = logic_bootstrap(configuration, echoes_game_description,
                                  patches)

    # Run
    reach = GeneratorReach.reach_from_state(game, state)

    # Assert
    assert len(list(reach.nodes)) == 26
    assert len(list(reach.safe_nodes)) == 4
Exemplo n.º 11
0
def test_reach_size_from_start(echoes_game_description,
                               default_layout_configuration):
    # Setup
    layout_configuration = dataclasses.replace(
        default_layout_configuration,
        trick_level_configuration=TrickLevelConfiguration(
            LayoutTrickLevel.HYPERMODE),
    )
    player_pool = generator.create_player_pool(Random(15000),
                                               layout_configuration, 0)

    game, state = logic_bootstrap(layout_configuration, player_pool.game,
                                  player_pool.patches)

    # Run
    reach = GeneratorReach.reach_from_state(game, state)

    # Assert
    assert len(list(reach.nodes)) == 44
    assert len(list(reach.safe_nodes)) == 5
Exemplo n.º 12
0
def _calculate_progression_pickups(pickups_left: Iterator[PickupEntry],
                                   reach: GeneratorReach,
                                   ) -> Tuple[PickupEntry, ...]:
    satisfiable_requirements: FrozenSet[RequirementList] = frozenset(itertools.chain.from_iterable(
        requirements.alternatives
        for requirements in reach.unreachable_nodes_with_requirements().values()
    ))
    interesting_resources = calculate_interesting_resources(
        satisfiable_requirements,
        reach.state.resources,
        reach.state.energy,
        reach.state.resource_database
    )

    progression_pickups = []

    for pickup in pickups_left:
        if pickup in progression_pickups:
            continue
        if _resources_in_pickup(pickup, reach.state.resources).intersection(interesting_resources):
            progression_pickups.append(pickup)

    return tuple(progression_pickups)
Exemplo n.º 13
0
def test_reach_size_from_start(echoes_game_description,
                               default_layout_configuration):
    # Setup
    configuration = dataclasses.replace(
        default_layout_configuration,
        trick_level_configuration=TrickLevelConfiguration(
            LayoutTrickLevel.HYPERMODE),
    )
    patches = echoes_game_description.create_game_patches()
    patches = patches.assign_gate_assignment(
        base_patches_factory.gate_assignment_for_configuration(
            configuration, echoes_game_description.resource_database,
            Random(15000)))

    game, state = logic_bootstrap(configuration, echoes_game_description,
                                  patches)

    # Run
    reach = GeneratorReach.reach_from_state(game, state)

    # Assert
    assert len(list(reach.nodes)) == 25
    assert len(list(reach.safe_nodes)) == 4
Exemplo n.º 14
0
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
Exemplo n.º 15
0
def _filter_collectable(resource_nodes: Iterator[ResourceNode],
                        reach: GeneratorReach) -> Iterator[ResourceNode]:
    for resource_node in resource_nodes:
        if resource_node.can_collect(reach.node_context()):
            yield resource_node
Exemplo n.º 16
0
def _filter_reachable(nodes: Iterator[Node],
                      reach: GeneratorReach) -> Iterator[Node]:
    for node in nodes:
        if reach.is_reachable_node(node):
            yield node
Exemplo n.º 17
0
def _get_safe_resources(reach: GeneratorReach) -> Iterator[ResourceNode]:
    yield from _filter_reachable(
        _filter_out_dangerous_actions(
            collectable_resource_nodes(reach.safe_nodes, reach), reach.game,
            reach.node_context()), reach)