RoR2: Remove recursion from explore mode access rules (#3681)

The access rules for "<Environment name> Chest n", "<Environment name>
Shrine n" etc. locations recursively called state.can_reach() for the
n-1 location name, with the n=1 location being the only location to have
the actual access rule set.

This patch removes the recursion, instead setting the actual access rule
directly on each location, increasing the performance of checking
accessibility of n>1 locations.

Risk of Rain 2 was already quite fast to generate despite the recursion
in the access rules, but with this patch, generating a multiworld with
200 copies of the template RoR2 yaml (and progression balancing
disabled through a meta.yaml) goes from about 18s to about 6s for me.

From generating the same seed before and after this patch, the same
result is produced.
This commit is contained in:
Mysteryem 2024-08-07 22:57:07 +01:00 committed by GitHub
parent 74697b679e
commit 05ce29f7dc
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
1 changed files with 6 additions and 12 deletions

View File

@ -31,23 +31,17 @@ def has_all_items(multiworld: MultiWorld, items: Set[str], region: str, player:
# Checks to see if chest/shrine are accessible
def has_location_access_rule(multiworld: MultiWorld, environment: str, player: int, item_number: int, item_type: str)\
-> None:
if item_number == 1:
multiworld.get_location(f"{environment}: {item_type} {item_number}", player).access_rule = \
lambda state: state.has(environment, player)
location_name = f"{environment}: {item_type} {item_number}"
if item_type == "Scavenger":
# scavengers need to be locked till after a full loop since that is when they are capable of spawning.
# (While technically the requirement is just beating 5 stages, this will ensure that the player will have
# a long enough run to have enough director credits for scavengers and
# help prevent being stuck in the same stages until that point).
if item_type == "Scavenger":
multiworld.get_location(f"{environment}: {item_type} {item_number}", player).access_rule = \
lambda state: state.has(environment, player) and state.has("Stage 5", player)
multiworld.get_location(location_name, player).access_rule = \
lambda state: state.has(environment, player) and state.has("Stage 5", player)
else:
multiworld.get_location(f"{environment}: {item_type} {item_number}", player).access_rule = \
lambda state: check_location(state, environment, player, item_number, item_type)
def check_location(state, environment: str, player: int, item_number: int, item_name: str) -> bool:
return state.can_reach(f"{environment}: {item_name} {item_number - 1}", "Location", player)
multiworld.get_location(location_name, player).access_rule = \
lambda state: state.has(environment, player)
def set_rules(ror2_world: "RiskOfRainWorld") -> None: