Archipelago
Archipelago copied to clipboard
The Witness: Rules Optimisation
The rules in The Witness are automatically generated in a "RandoCore" kind of way.
This means that each requirement is a Set[Set[str]], and is then converted first to a List[List[CollectionRule]], and then to a CollectionRule via any(all(...) ...)
This introduces a lot of function call overhead.
In this PR, I aimed to catch some of these cases.
- If the rule is empty, it no longer sets
lambda state: any(all([[]])), instead it just skips setting an access rule. - If the rule only has one access option (
len(rule) == 1), we skip the outeranyand just callallon the one option that exists. - If the rule only has one access option (
len(rule) == 1) and that one option only has a single element (len(rule[0]) == 1), we skip both theanyand thealland set the singular CollectionRule as the access rule directly. - If an access option only contains item requirements (as opposed to region requirements), we collect them and use
state.has_all_counts, instead of chaining togetherstate.hasin an inefficient way. - Laser events have been simplified. They aren't as simple as I wish they were, but that's because of a legitimate difference in how some checks require the Desert Laser to be redirected, and others do not.
Tested Using the unit tests added in a different PR, and by comparing outputs with the same seed
Benchmark
This leads to tangible improvements - A two player MultiWorld with shuffle_doors: panels generates in 0.78s instead of 0.95s.
Drafted for now because I'm still debating how I want to structure this code. Also, it's based on the panel hunt PR because of a change that PR makes to how lasers are counted.