Skip to content

Conversation

@mattman107
Copy link

@mattman107 mattman107 commented Nov 2, 2025

Original PR: aMannus#278
#6

Just cherrypicked and fixed merge conflicts. Still has the originals issues.

@mattman107 mattman107 changed the title Entrance rando new Entrance Rando Nov 2, 2025
@mattman107
Copy link
Author

mattman107 commented Nov 3, 2025

So my solution to the Sheik at Colossus location is to move it when dungeon entrances are randomized (Probably could also only be when entrances are decoupled as that is the only time it really matters. Just haven't gotten that working yet). The parent region of the location will be changed to the parent region of the dungeon exit that is connected to Desert Colossus.

It feels kinda hacky, but it is technically also true. If you are able to get to the entrance that leads to desert colossus, the location is accessible.

@mattman107
Copy link
Author

Note to self remove print from on_connect

@mattman107
Copy link
Author

mattman107 commented Nov 7, 2025

@ScipioWright Mind checking this out when you get a chance?

The state this is in right now, when boss entrances are shuffled to full and dungeon entrances are shuffled at all it will try to randomized them both at the same time (groupings preventing them from touching each other just yet).

The problem comes in when it reaches entrance_rando.pys find_placeable_exits. When both boss and dungeon entrances are in the usable exits list together, the boss entrances are never in collection_state.blocked_connections which makes the boss entrances not applicable to be added to placeable_randomized_exits.

def find_placeable_exits(self, check_validity: bool, usable_exits: list[Entrance]) -> list[Entrance]:
        if check_validity:
            blocked_connections = self.collection_state.blocked_connections[self.world.player]
            placeable_randomized_exits = [ex for ex in usable_exits
                                          if not ex.connected_region
                                          and ex in blocked_connections
                                          and ex.is_valid_source_transition(self)]
        else:
            # this is on a beaten minimal attempt, so any exit anywhere is fair game
            placeable_randomized_exits = [ex for ex in usable_exits if not ex.connected_region]
        self.world.random.shuffle(placeable_randomized_exits)
        return placeable_randomized_exits

I'm not 100% sure what makes an entrance get put in the blocked_connections dictionary which is kinda putting me at a dead end... I guess more so I'm not sure why the boss entrances aren't getting put in there.

@ScipioWright
Copy link

Sorry, I have basically no experience with AP's generic entrance rando API, you're better off asking in apworld-dev or the GER thread

…trances into dungeon entrances though as dungeon entrances are like sudo dead ends. It like to keep goes as much as it can.
@mattman107
Copy link
Author

I don't love the need to have manual retries, but it technically works. Was one of the recommendations from the GER thread on discord.

With that said, this is my proposed solution/general structure for entrance randomization in the SOH AP world.

The entrances groups need be tweaked a bit more to prevent errors and such, but this seems like the way GER wants it done.

Disable decouple and mixed options as they don't work
@mattman107
Copy link
Author

mattman107 commented Nov 15, 2025

I think our can_reach function on region is preventing this implementation of the GER from working when some entrances are locked behind others. One of the things the GER needs to function is determine if the entrances is a valid source transition:

    def is_valid_source_transition(self, er_state: "ERPlacementState") -> bool:
        """
        Determines whether this is a valid source transition, that is, whether the entrance
        randomizer is allowed to pair it to place any other regions. By default, this is the
        same as a reachability check, but can be modified by Entrance implementations to add
        other restrictions based on the placement state.

        :param er_state: The current (partial) state of the ongoing entrance randomization
        """
        return self.can_reach(er_state.collection_state)

as well as if it is contained in the collection_state.blocked_connections set as I said here.

I think what is happening is that we disconnect the dungeon entrances, and our can_reach function is unable to then get to the boss entrances, so they are almost always considered unreachable.

Swapping out our can_reach for the built in one allows the GER to place all entrances perfectly fine.

This is going to prevent us from randomizing entrances at the same time as ones that block them and mixing entrance pools.

How to fix that... is something I am unsure about. @jeromkiller maybe you have ideas?

@mattman107
Copy link
Author

Looks like the solution to the problem was really small. Just needed to make our _soh_stale for the given player True so it would continue to scan the regions. Seems to be functioning good now.

I'm working through interior entrances now, then will push through overworld.

At the point where the entrance from dampes grave to windmill is a problem. Sometimes the GER will force two "exits" together that don't lead to anywhere else.
Still hit or miss on a solo rando, but multiworld allows it to work way better.
@mattman107 mattman107 mentioned this pull request Nov 26, 2025
@mattman107 mattman107 marked this pull request as ready for review November 27, 2025 18:40
@mattman107
Copy link
Author

mattman107 commented Nov 27, 2025

This is ready for review/comments/feedback, but definitely still needs work. It isn't perfect, but it technically can randomize the entrances and generate logically beatable randos.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants