From 1ca8d3e4a8b4a4a3850a0829c7c934bc4f8475c6 Mon Sep 17 00:00:00 2001 From: qwint Date: Thu, 12 Dec 2024 15:24:38 -0500 Subject: [PATCH] Docs: add description of Indirect Condition problem (#4295) * Docs: Dev FAQ - About indirect conditions I wrote up a big effortpost about indirect conditions for nex on the [DS3 3.0 PR](https://github.com/ArchipelagoMW/Archipelago/pull/3128#discussion_r1693843193). The version I'm [PRing to the world API document](https://github.com/ArchipelagoMW/Archipelago/pull/3552) is very brief and unnuanced, because I'd rather people use too many indirect conditions than too few. But that might leave some devs wanting to know more. I think that comment on nex's DS3 PR is probably the best detailed explanation for indirect conditions that exists currently. So I think it's good if it exists somewhere. And the FAQ doc seems like the best place right now, because I don't want to write an entirely new doc at the moment. * Actually copy in the text * Update docs/apworld_dev_faq.md Co-authored-by: Exempt-Medic <60412657+Exempt-Medic@users.noreply.github.com> * Update docs/apworld_dev_faq.md Co-authored-by: Exempt-Medic <60412657+Exempt-Medic@users.noreply.github.com> * Update docs/apworld_dev_faq.md Co-authored-by: Exempt-Medic <60412657+Exempt-Medic@users.noreply.github.com> * Update docs/apworld_dev_faq.md Co-authored-by: Exempt-Medic <60412657+Exempt-Medic@users.noreply.github.com> * Update docs/apworld_dev_faq.md Co-authored-by: Exempt-Medic <60412657+Exempt-Medic@users.noreply.github.com> * Update docs/apworld_dev_faq.md Co-authored-by: Scipio Wright * Update docs/apworld_dev_faq.md Co-authored-by: Scipio Wright * Update docs/apworld_dev_faq.md Co-authored-by: qwint * Update docs/apworld_dev_faq.md Co-authored-by: qwint * Update apworld_dev_faq.md * Update docs/apworld_dev_faq.md Co-authored-by: Exempt-Medic <60412657+Exempt-Medic@users.noreply.github.com> * Update apworld_dev_faq.md * Update docs/apworld_dev_faq.md Co-authored-by: Exempt-Medic <60412657+Exempt-Medic@users.noreply.github.com> * Update docs/apworld_dev_faq.md Co-authored-by: Exempt-Medic <60412657+Exempt-Medic@users.noreply.github.com> * Update docs/apworld_dev_faq.md Co-authored-by: Exempt-Medic <60412657+Exempt-Medic@users.noreply.github.com> * Update apworld_dev_faq.md * Update docs/apworld_dev_faq.md Co-authored-by: qwint * Update docs/apworld_dev_faq.md Co-authored-by: qwint * fix the last couple of wording issues I have with the indirect condition section to apworld dev faq doc * I didn't like that wording * Apply suggestions from code review Co-authored-by: Scipio Wright * Apply suggestions from code review Co-authored-by: Scipio Wright * Update docs/apworld_dev_faq.md Co-authored-by: Scipio Wright * Update docs/apworld_dev_faq.md * Update docs/apworld_dev_faq.md Co-authored-by: Scipio Wright --------- Co-authored-by: NewSoupVi <57900059+NewSoupVi@users.noreply.github.com> Co-authored-by: Exempt-Medic <60412657+Exempt-Medic@users.noreply.github.com> Co-authored-by: Scipio Wright --- docs/apworld_dev_faq.md | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/docs/apworld_dev_faq.md b/docs/apworld_dev_faq.md index 8d9429afa321..769a2fb3a0a7 100644 --- a/docs/apworld_dev_faq.md +++ b/docs/apworld_dev_faq.md @@ -43,3 +43,26 @@ A faster alternative to the `for` loop would be to use a [list comprehension](ht ```py item_pool += [self.create_filler() for _ in range(total_locations - len(item_pool))] ``` + +--- + +### I learned about indirect conditions in the world API document, but I want to know more. What are they and why are they necessary? + +The world API document mentions how to use `multiworld.register_indirect_condition` to register indirect conditions and **when** you should use them, but not *how* they work and *why* they are necessary. This is because the explanation is quite complicated. + +Region sweep (the algorithm that determines which regions are reachable) is a Breadth-First Search of the region graph. It starts from the origin region, checks entrances one by one, and adds newly reached regions and their entrances to the queue until there is nothing more to check. + +For performance reasons, AP only checks every entrance once. However, if an entrance's access_rule depends on region access, then the following may happen: +1. The entrance is checked and determined to be nontraversable because the region in its access_rule hasn't been reached yet during the graph search. +2. Then, the region in its access_rule is determined to be reachable. + +This entrance *would* be in logic if it were rechecked, but it won't be rechecked this cycle. +To account for this case, AP would have to recheck all entrances every time a new region is reached until no new regions are reached. + +An indirect condition is how you can manually define that a specific entrance needs to be rechecked during region sweep if a specific region is reached during it. +This keeps most of the performance upsides. Even in a game making heavy use of indirect conditions (ex: The Witness), using them is significantly faster than just "rechecking each entrance until nothing new is found". +The reason entrance access rules using `location.can_reach` and `entrance.can_reach` are also affected is because they call `region.can_reach` on their respective parent/source region. + +We recognize it can feel like a trap since it will not alert you when you are missing an indirect condition, and that some games have very complex access rules. +As of [PR #3682 (Core: Region handling customization)](https://github.com/ArchipelagoMW/Archipelago/pull/3682) being merged, it is possible for a world to opt out of indirect conditions entirely, instead using the system of checking each entrance whenever a region has been reached, although this does come with a performance cost. +Opting out of using indirect conditions should only be used by games that *really* need it. For most games, it should be reasonable to know all entrance → region dependencies, making indirect conditions preferred because they are much faster.