From db5be6a4117588c63eb5554a89633b2a19a26476 Mon Sep 17 00:00:00 2001 From: NewSoupVi <57900059+NewSoupVi@users.noreply.github.com> Date: Sat, 27 Jul 2024 08:18:00 +0200 Subject: [PATCH 01/27] 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. --- docs/apworld_dev_faq.md | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/docs/apworld_dev_faq.md b/docs/apworld_dev_faq.md index 8d9429afa321..eb725b33005c 100644 --- a/docs/apworld_dev_faq.md +++ b/docs/apworld_dev_faq.md @@ -43,3 +43,11 @@ 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 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. + +It might get its own document in the future, but for now, you can read [this comment written by NewSoupVi](https://github.com/ArchipelagoMW/Archipelago/pull/3128#discussion_r1693843193) (and the other comments in that reply thread if you're still curious to learn more). As of the time of writing, it reflects the most up to date understanding of indirect conditions. From 295e719ef37965abf99ec838703fb72198f09eba Mon Sep 17 00:00:00 2001 From: NewSoupVi <57900059+NewSoupVi@users.noreply.github.com> Date: Wed, 31 Jul 2024 19:34:37 +0200 Subject: [PATCH 02/27] Actually copy in the text --- docs/apworld_dev_faq.md | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/docs/apworld_dev_faq.md b/docs/apworld_dev_faq.md index eb725b33005c..6d22581869f8 100644 --- a/docs/apworld_dev_faq.md +++ b/docs/apworld_dev_faq.md @@ -50,4 +50,19 @@ item_pool += [self.create_filler() for _ in range(total_locations - len(item_poo The world API document mentions 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. -It might get its own document in the future, but for now, you can read [this comment written by NewSoupVi](https://github.com/ArchipelagoMW/Archipelago/pull/3128#discussion_r1693843193) (and the other comments in that reply thread if you're still curious to learn more). As of the time of writing, it reflects the most up to date understanding of indirect conditions. +Region sweep (the algorithm that determines with regions are reachable) is a Breadth First Search of the region graph from the Menu region, checking entrances one by one and adding newly reached nodes (regions) and their entrances to the queue until there is nothing more to check. + +However, if entrance access conditions depend on regions, then it is possible for this to happen: +1. An entrance that depends on a region is checked and determined to be intraversible because the region hasn't been reached yet during the graph search +2. After that, the region is reached by the graph search. The entrance *would* now be determined as traversible if it were rechecked. + +To account for this case, we would have to recheck all entrances every time a new region is reached, until no new regions are reached. + +Because most games do not check for region access inside of entrance access conditions, AP has decided to **eschew this rechecking** and just checks every entrance once. This gives a significant performance gain to AP as a whole, about 30%-50%. + +However, because some games *did* start using things like `region.can_reach` inside entrance access conditions, we provided a way to **manually** define that a *specific* entrance needs to be rechecked during region sweep if a *specific* region is reached during it. This is what an indirect condition is. +This keeps almost all of the performance upsides. Even a game making heavy use of indirect conditions (See: The Witness) is still way way faster than if it just blanket "rechecked all entrances until nothing new is found". +The reason `location.can_reach` and `entrance.can_reach` are also affected is simple: They call `region.can_reach` on their respective parent/source region. + +We recognize it's a pretty bad beginner's trap (heck, not even a "beginner's" trap, just a trap - even for experienced AP devs), and some games are very complex with their access rules. +There is an open Pull Request that makes this behavior optional via a world class attribute: [Core: Region handling customization](https://github.com/ArchipelagoMW/Archipelago/pull/3682) From f9b07a5b9a65c86a0fefd733ac0467020ddbd9b2 Mon Sep 17 00:00:00 2001 From: NewSoupVi <57900059+NewSoupVi@users.noreply.github.com> Date: Wed, 31 Jul 2024 22:33:36 +0200 Subject: [PATCH 03/27] Update docs/apworld_dev_faq.md Co-authored-by: Exempt-Medic <60412657+Exempt-Medic@users.noreply.github.com> --- docs/apworld_dev_faq.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/apworld_dev_faq.md b/docs/apworld_dev_faq.md index 6d22581869f8..8eb236a42133 100644 --- a/docs/apworld_dev_faq.md +++ b/docs/apworld_dev_faq.md @@ -50,7 +50,7 @@ item_pool += [self.create_filler() for _ in range(total_locations - len(item_poo The world API document mentions 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 with regions are reachable) is a Breadth First Search of the region graph from the Menu region, checking entrances one by one and adding newly reached nodes (regions) and their entrances to the queue until there is nothing more to check. +Region sweep (the algorithm that determines which regions are reachable) is a Breadth First Search of the region graph from the Menu region, checking entrances one by one and adding newly reached nodes (regions) and their entrances to the queue until there is nothing more to check. However, if entrance access conditions depend on regions, then it is possible for this to happen: 1. An entrance that depends on a region is checked and determined to be intraversible because the region hasn't been reached yet during the graph search From 8420c72ec42336cc70600d076a413862ad5dcf38 Mon Sep 17 00:00:00 2001 From: NewSoupVi <57900059+NewSoupVi@users.noreply.github.com> Date: Wed, 31 Jul 2024 22:33:44 +0200 Subject: [PATCH 04/27] Update docs/apworld_dev_faq.md Co-authored-by: Exempt-Medic <60412657+Exempt-Medic@users.noreply.github.com> --- docs/apworld_dev_faq.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/apworld_dev_faq.md b/docs/apworld_dev_faq.md index 8eb236a42133..5f0e8c415db0 100644 --- a/docs/apworld_dev_faq.md +++ b/docs/apworld_dev_faq.md @@ -53,7 +53,7 @@ The world API document mentions indirect conditions and **when** you should use Region sweep (the algorithm that determines which regions are reachable) is a Breadth First Search of the region graph from the Menu region, checking entrances one by one and adding newly reached nodes (regions) and their entrances to the queue until there is nothing more to check. However, if entrance access conditions depend on regions, then it is possible for this to happen: -1. An entrance that depends on a region is checked and determined to be intraversible because the region hasn't been reached yet during the graph search +1. An entrance that depends on a region is checked and determined to be untraversable because the region hasn't been reached yet during the graph search. 2. After that, the region is reached by the graph search. The entrance *would* now be determined as traversible if it were rechecked. To account for this case, we would have to recheck all entrances every time a new region is reached, until no new regions are reached. From 205fa71cc74aa7276f6577bca3e65b78891be18e Mon Sep 17 00:00:00 2001 From: NewSoupVi <57900059+NewSoupVi@users.noreply.github.com> Date: Wed, 31 Jul 2024 22:33:50 +0200 Subject: [PATCH 05/27] Update docs/apworld_dev_faq.md Co-authored-by: Exempt-Medic <60412657+Exempt-Medic@users.noreply.github.com> --- docs/apworld_dev_faq.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/apworld_dev_faq.md b/docs/apworld_dev_faq.md index 5f0e8c415db0..986443a3a06d 100644 --- a/docs/apworld_dev_faq.md +++ b/docs/apworld_dev_faq.md @@ -54,7 +54,7 @@ Region sweep (the algorithm that determines which regions are reachable) is a Br However, if entrance access conditions depend on regions, then it is possible for this to happen: 1. An entrance that depends on a region is checked and determined to be untraversable because the region hasn't been reached yet during the graph search. -2. After that, the region is reached by the graph search. The entrance *would* now be determined as traversible if it were rechecked. +2. After that, the region is reached by the graph search. The entrance *would* now be determined to be traversable if it were rechecked. To account for this case, we would have to recheck all entrances every time a new region is reached, until no new regions are reached. From 3a70bf9f4f35d75b8e781f7e1a2f91e841d06a4f Mon Sep 17 00:00:00 2001 From: NewSoupVi <57900059+NewSoupVi@users.noreply.github.com> Date: Wed, 31 Jul 2024 22:33:57 +0200 Subject: [PATCH 06/27] Update docs/apworld_dev_faq.md Co-authored-by: Exempt-Medic <60412657+Exempt-Medic@users.noreply.github.com> --- docs/apworld_dev_faq.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/apworld_dev_faq.md b/docs/apworld_dev_faq.md index 986443a3a06d..4d2da9a9ead1 100644 --- a/docs/apworld_dev_faq.md +++ b/docs/apworld_dev_faq.md @@ -65,4 +65,4 @@ This keeps almost all of the performance upsides. Even a game making heavy use o The reason `location.can_reach` and `entrance.can_reach` are also affected is simple: They call `region.can_reach` on their respective parent/source region. We recognize it's a pretty bad beginner's trap (heck, not even a "beginner's" trap, just a trap - even for experienced AP devs), and some games are very complex with their access rules. -There is an open Pull Request that makes this behavior optional via a world class attribute: [Core: Region handling customization](https://github.com/ArchipelagoMW/Archipelago/pull/3682) +There is an open Pull Request that makes this behavior optional via a world class attribute: [Core: Region handling customization](https://github.com/ArchipelagoMW/Archipelago/pull/3682). From 850033b31150672731a3c13b6cd27161430ca114 Mon Sep 17 00:00:00 2001 From: NewSoupVi <57900059+NewSoupVi@users.noreply.github.com> Date: Wed, 31 Jul 2024 22:34:10 +0200 Subject: [PATCH 07/27] Update docs/apworld_dev_faq.md Co-authored-by: Exempt-Medic <60412657+Exempt-Medic@users.noreply.github.com> --- docs/apworld_dev_faq.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/apworld_dev_faq.md b/docs/apworld_dev_faq.md index 4d2da9a9ead1..bb00754aa06a 100644 --- a/docs/apworld_dev_faq.md +++ b/docs/apworld_dev_faq.md @@ -62,7 +62,7 @@ Because most games do not check for region access inside of entrance access cond However, because some games *did* start using things like `region.can_reach` inside entrance access conditions, we provided a way to **manually** define that a *specific* entrance needs to be rechecked during region sweep if a *specific* region is reached during it. This is what an indirect condition is. This keeps almost all of the performance upsides. Even a game making heavy use of indirect conditions (See: The Witness) is still way way faster than if it just blanket "rechecked all entrances until nothing new is found". -The reason `location.can_reach` and `entrance.can_reach` are also affected is simple: They call `region.can_reach` on their respective parent/source region. +The reason entrance access rules using `location.can_reach` and `entrance.can_reach` are also affected is simple: They call `region.can_reach` on their respective parent/source region. We recognize it's a pretty bad beginner's trap (heck, not even a "beginner's" trap, just a trap - even for experienced AP devs), and some games are very complex with their access rules. There is an open Pull Request that makes this behavior optional via a world class attribute: [Core: Region handling customization](https://github.com/ArchipelagoMW/Archipelago/pull/3682). From e74e472e3ff27534013a691e06f13d448387ae17 Mon Sep 17 00:00:00 2001 From: NewSoupVi <57900059+NewSoupVi@users.noreply.github.com> Date: Tue, 13 Aug 2024 18:18:55 +0200 Subject: [PATCH 08/27] Update docs/apworld_dev_faq.md Co-authored-by: Scipio Wright --- docs/apworld_dev_faq.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/apworld_dev_faq.md b/docs/apworld_dev_faq.md index bb00754aa06a..c08700fc79fb 100644 --- a/docs/apworld_dev_faq.md +++ b/docs/apworld_dev_faq.md @@ -53,7 +53,7 @@ The world API document mentions indirect conditions and **when** you should use Region sweep (the algorithm that determines which regions are reachable) is a Breadth First Search of the region graph from the Menu region, checking entrances one by one and adding newly reached nodes (regions) and their entrances to the queue until there is nothing more to check. However, if entrance access conditions depend on regions, then it is possible for this to happen: -1. An entrance that depends on a region is checked and determined to be untraversable because the region hasn't been reached yet during the graph search. +1. An entrance that depends on a region is checked and determined to be nontraversable because the region hasn't been reached yet during the graph search. 2. After that, the region is reached by the graph search. The entrance *would* now be determined to be traversable if it were rechecked. To account for this case, we would have to recheck all entrances every time a new region is reached, until no new regions are reached. From 9ec1f8de6ea1372b1c70188f873548be2e48208a Mon Sep 17 00:00:00 2001 From: NewSoupVi <57900059+NewSoupVi@users.noreply.github.com> Date: Tue, 13 Aug 2024 18:19:21 +0200 Subject: [PATCH 09/27] Update docs/apworld_dev_faq.md Co-authored-by: Scipio Wright --- docs/apworld_dev_faq.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/apworld_dev_faq.md b/docs/apworld_dev_faq.md index c08700fc79fb..b5e7a81645e6 100644 --- a/docs/apworld_dev_faq.md +++ b/docs/apworld_dev_faq.md @@ -64,5 +64,5 @@ However, because some games *did* start using things like `region.can_reach` ins This keeps almost all of the performance upsides. Even a game making heavy use of indirect conditions (See: The Witness) is still way way faster than if it just blanket "rechecked all entrances until nothing new is found". The reason entrance access rules using `location.can_reach` and `entrance.can_reach` are also affected is simple: They call `region.can_reach` on their respective parent/source region. -We recognize it's a pretty bad beginner's trap (heck, not even a "beginner's" trap, just a trap - even for experienced AP devs), and some games are very complex with their access rules. +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. There is an open Pull Request that makes this behavior optional via a world class attribute: [Core: Region handling customization](https://github.com/ArchipelagoMW/Archipelago/pull/3682). From 49394bebdaafed697f04b9a4b5cfcdb677eafefc Mon Sep 17 00:00:00 2001 From: NewSoupVi <57900059+NewSoupVi@users.noreply.github.com> Date: Thu, 5 Sep 2024 18:55:58 +0200 Subject: [PATCH 10/27] Update docs/apworld_dev_faq.md Co-authored-by: qwint --- docs/apworld_dev_faq.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/apworld_dev_faq.md b/docs/apworld_dev_faq.md index b5e7a81645e6..97bd525d4ecb 100644 --- a/docs/apworld_dev_faq.md +++ b/docs/apworld_dev_faq.md @@ -60,7 +60,7 @@ To account for this case, we would have to recheck all entrances every time a ne Because most games do not check for region access inside of entrance access conditions, AP has decided to **eschew this rechecking** and just checks every entrance once. This gives a significant performance gain to AP as a whole, about 30%-50%. -However, because some games *did* start using things like `region.can_reach` inside entrance access conditions, we provided a way to **manually** define that a *specific* entrance needs to be rechecked during region sweep if a *specific* region is reached during it. This is what an indirect condition is. +However, there is a way to **manually** define that a *specific* entrance needs to be rechecked during region sweep if a *specific* region is reached during it. This is what an indirect condition is. This keeps almost all of the performance upsides. Even a game making heavy use of indirect conditions (See: The Witness) is still way way faster than if it just blanket "rechecked all entrances until nothing new is found". The reason entrance access rules using `location.can_reach` and `entrance.can_reach` are also affected is simple: They call `region.can_reach` on their respective parent/source region. From 1d8d04ea03ab7ef6e453c56a9c31406236827308 Mon Sep 17 00:00:00 2001 From: NewSoupVi <57900059+NewSoupVi@users.noreply.github.com> Date: Thu, 5 Sep 2024 18:56:33 +0200 Subject: [PATCH 11/27] Update docs/apworld_dev_faq.md Co-authored-by: qwint --- docs/apworld_dev_faq.md | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/docs/apworld_dev_faq.md b/docs/apworld_dev_faq.md index 97bd525d4ecb..66b100f30a2f 100644 --- a/docs/apworld_dev_faq.md +++ b/docs/apworld_dev_faq.md @@ -52,13 +52,11 @@ The world API document mentions indirect conditions and **when** you should use Region sweep (the algorithm that determines which regions are reachable) is a Breadth First Search of the region graph from the Menu region, checking entrances one by one and adding newly reached nodes (regions) and their entrances to the queue until there is nothing more to check. -However, if entrance access conditions depend on regions, then it is possible for this to happen: +For performance reasons AP only checks every entrance once. However, if entrance access conditions depend on regions, then it is possible for this to happen: 1. An entrance that depends on a region is checked and determined to be nontraversable because the region hasn't been reached yet during the graph search. 2. After that, the region is reached by the graph search. The entrance *would* now be determined to be traversable if it were rechecked. -To account for this case, we would have to recheck all entrances every time a new region is reached, until no new regions are reached. - -Because most games do not check for region access inside of entrance access conditions, AP has decided to **eschew this rechecking** and just checks every entrance once. This gives a significant performance gain to AP as a whole, about 30%-50%. +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. However, there is a way to **manually** define that a *specific* entrance needs to be rechecked during region sweep if a *specific* region is reached during it. This is what an indirect condition is. This keeps almost all of the performance upsides. Even a game making heavy use of indirect conditions (See: The Witness) is still way way faster than if it just blanket "rechecked all entrances until nothing new is found". From cf3d4ff83772c84b6bf6ce6669a3f69eafbbb178 Mon Sep 17 00:00:00 2001 From: NewSoupVi <57900059+NewSoupVi@users.noreply.github.com> Date: Thu, 5 Sep 2024 19:04:07 +0200 Subject: [PATCH 12/27] Update apworld_dev_faq.md --- docs/apworld_dev_faq.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/docs/apworld_dev_faq.md b/docs/apworld_dev_faq.md index 66b100f30a2f..33a07fc05fe5 100644 --- a/docs/apworld_dev_faq.md +++ b/docs/apworld_dev_faq.md @@ -63,4 +63,5 @@ This keeps almost all of the performance upsides. Even a game making heavy use o The reason entrance access rules using `location.can_reach` and `entrance.can_reach` are also affected is simple: 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. -There is an open Pull Request that makes this behavior optional via a world class attribute: [Core: Region handling customization](https://github.com/ArchipelagoMW/Archipelago/pull/3682). +As of [PR #3682 (Core: Region handling customization)](https://github.com/ArchipelagoMW/Archipelago/pull/3682) being merged, it is also possible for a world to opt out of indirect conditions entirely, although it does come at a flat performance cost. +It should only be used by games that *really* need it. For most games, it should be reasonable to know all entrance->region dependencies, and in this case, indirect conditions are still preferred because they are faster. From 663b5a28a51f0bb3806cf9fa691f72ce8cf04269 Mon Sep 17 00:00:00 2001 From: NewSoupVi <57900059+NewSoupVi@users.noreply.github.com> Date: Thu, 5 Sep 2024 21:20:10 +0200 Subject: [PATCH 13/27] Update docs/apworld_dev_faq.md Co-authored-by: Exempt-Medic <60412657+Exempt-Medic@users.noreply.github.com> --- docs/apworld_dev_faq.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/apworld_dev_faq.md b/docs/apworld_dev_faq.md index 33a07fc05fe5..94c8fda5b357 100644 --- a/docs/apworld_dev_faq.md +++ b/docs/apworld_dev_faq.md @@ -50,7 +50,7 @@ item_pool += [self.create_filler() for _ in range(total_locations - len(item_poo The world API document mentions 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 from the Menu region, checking entrances one by one and adding newly reached nodes (regions) and their entrances to the queue until there is nothing more to check. +Region sweep (the algorithm that determines which regions are reachable) is a Breadth-First Search of the region graph from the Menu region, checking entrances one by one and adding newly reached nodes (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 entrance access conditions depend on regions, then it is possible for this to happen: 1. An entrance that depends on a region is checked and determined to be nontraversable because the region hasn't been reached yet during the graph search. From a1779c1924b40c7b30df9dddb52d1a1661e3323f Mon Sep 17 00:00:00 2001 From: NewSoupVi <57900059+NewSoupVi@users.noreply.github.com> Date: Thu, 5 Sep 2024 21:20:35 +0200 Subject: [PATCH 14/27] Update apworld_dev_faq.md --- docs/apworld_dev_faq.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/apworld_dev_faq.md b/docs/apworld_dev_faq.md index 94c8fda5b357..4221732548c7 100644 --- a/docs/apworld_dev_faq.md +++ b/docs/apworld_dev_faq.md @@ -50,7 +50,7 @@ item_pool += [self.create_filler() for _ in range(total_locations - len(item_poo The world API document mentions 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 from the Menu region, checking entrances one by one and adding newly reached nodes (regions) and their entrances to the queue until there is nothing more to check. +Region sweep (the algorithm that determines which regions are reachable) is a Breadth-First Search of the region graph from the origin region, checking entrances one by one and adding newly reached nodes (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 entrance access conditions depend on regions, then it is possible for this to happen: 1. An entrance that depends on a region is checked and determined to be nontraversable because the region hasn't been reached yet during the graph search. From 8cefe85630c02d8a4af34301dee7d5fc03a18f85 Mon Sep 17 00:00:00 2001 From: NewSoupVi <57900059+NewSoupVi@users.noreply.github.com> Date: Thu, 5 Sep 2024 21:20:51 +0200 Subject: [PATCH 15/27] Update docs/apworld_dev_faq.md Co-authored-by: Exempt-Medic <60412657+Exempt-Medic@users.noreply.github.com> --- docs/apworld_dev_faq.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/apworld_dev_faq.md b/docs/apworld_dev_faq.md index 4221732548c7..690265593b1d 100644 --- a/docs/apworld_dev_faq.md +++ b/docs/apworld_dev_faq.md @@ -52,7 +52,7 @@ The world API document mentions indirect conditions and **when** you should use Region sweep (the algorithm that determines which regions are reachable) is a Breadth-First Search of the region graph from the origin region, checking entrances one by one and adding newly reached nodes (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 entrance access conditions depend on regions, then it is possible for this to happen: +For performance reasons, AP only checks every entrance once. However, if entrance access conditions depend on regions, then it is possible for this to happen: 1. An entrance that depends on a region is checked and determined to be nontraversable because the region hasn't been reached yet during the graph search. 2. After that, the region is reached by the graph search. The entrance *would* now be determined to be traversable if it were rechecked. From df1f3dc7309469714073b1252b3caf8f3d2d1abc Mon Sep 17 00:00:00 2001 From: NewSoupVi <57900059+NewSoupVi@users.noreply.github.com> Date: Thu, 5 Sep 2024 21:21:24 +0200 Subject: [PATCH 16/27] Update docs/apworld_dev_faq.md Co-authored-by: Exempt-Medic <60412657+Exempt-Medic@users.noreply.github.com> --- docs/apworld_dev_faq.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/apworld_dev_faq.md b/docs/apworld_dev_faq.md index 690265593b1d..2acb42836f01 100644 --- a/docs/apworld_dev_faq.md +++ b/docs/apworld_dev_faq.md @@ -59,7 +59,7 @@ For performance reasons, AP only checks every entrance once. However, if entranc 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. However, there is a way to **manually** define that a *specific* entrance needs to be rechecked during region sweep if a *specific* region is reached during it. This is what an indirect condition is. -This keeps almost all of the performance upsides. Even a game making heavy use of indirect conditions (See: The Witness) is still way way faster than if it just blanket "rechecked all entrances until nothing new is found". +This keeps almost all of the performance upsides. Even a game making heavy use of indirect conditions (See: The Witness) is still significantly faster than if it just blanket "rechecked all entrances until nothing new is found". The reason entrance access rules using `location.can_reach` and `entrance.can_reach` are also affected is simple: 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. From 153f454fb8881449adad0d41e6d24b2760f42519 Mon Sep 17 00:00:00 2001 From: NewSoupVi <57900059+NewSoupVi@users.noreply.github.com> Date: Thu, 5 Sep 2024 21:22:36 +0200 Subject: [PATCH 17/27] Update docs/apworld_dev_faq.md Co-authored-by: Exempt-Medic <60412657+Exempt-Medic@users.noreply.github.com> --- docs/apworld_dev_faq.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/apworld_dev_faq.md b/docs/apworld_dev_faq.md index 2acb42836f01..672d08e49b1d 100644 --- a/docs/apworld_dev_faq.md +++ b/docs/apworld_dev_faq.md @@ -64,4 +64,4 @@ The reason entrance access rules using `location.can_reach` and `entrance.can_re 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 also possible for a world to opt out of indirect conditions entirely, although it does come at a flat performance cost. -It should only be used by games that *really* need it. For most games, it should be reasonable to know all entrance->region dependencies, and in this case, indirect conditions are still preferred because they are faster. +It should only be used by games that *really* need it. For most games, it should be reasonable to know all entrance → region dependencies, and in this case, indirect conditions are still preferred because they are faster. From ce8d254912168accc59247340d8fdf3165e07256 Mon Sep 17 00:00:00 2001 From: NewSoupVi <57900059+NewSoupVi@users.noreply.github.com> Date: Thu, 5 Sep 2024 21:23:33 +0200 Subject: [PATCH 18/27] Update apworld_dev_faq.md --- docs/apworld_dev_faq.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/docs/apworld_dev_faq.md b/docs/apworld_dev_faq.md index 672d08e49b1d..b9e7361ffac1 100644 --- a/docs/apworld_dev_faq.md +++ b/docs/apworld_dev_faq.md @@ -54,8 +54,9 @@ Region sweep (the algorithm that determines which regions are reachable) is a Br For performance reasons, AP only checks every entrance once. However, if entrance access conditions depend on regions, then it is possible for this to happen: 1. An entrance that depends on a region is checked and determined to be nontraversable because the region hasn't been reached yet during the graph search. -2. After that, the region is reached by the graph search. The entrance *would* now be determined to be traversable if it were rechecked. +2. After that, the region is reached by the graph search. +The entrance *would* now be determined to be traversable if it were rechecked, but it is not. 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. However, there is a way to **manually** define that a *specific* entrance needs to be rechecked during region sweep if a *specific* region is reached during it. This is what an indirect condition is. From a2ba2f3dbf07bc22e7f263e9ad6f010ede9e3bc2 Mon Sep 17 00:00:00 2001 From: NewSoupVi <57900059+NewSoupVi@users.noreply.github.com> Date: Thu, 5 Sep 2024 21:30:30 +0200 Subject: [PATCH 19/27] Update docs/apworld_dev_faq.md Co-authored-by: qwint --- docs/apworld_dev_faq.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/apworld_dev_faq.md b/docs/apworld_dev_faq.md index b9e7361ffac1..fb9114c76fee 100644 --- a/docs/apworld_dev_faq.md +++ b/docs/apworld_dev_faq.md @@ -57,7 +57,7 @@ For performance reasons, AP only checks every entrance once. However, if entranc 2. After that, the region is reached by the graph search. The entrance *would* now be determined to be traversable if it were rechecked, but it is not. -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. +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. However, there is a way to **manually** define that a *specific* entrance needs to be rechecked during region sweep if a *specific* region is reached during it. This is what an indirect condition is. This keeps almost all of the performance upsides. Even a game making heavy use of indirect conditions (See: The Witness) is still significantly faster than if it just blanket "rechecked all entrances until nothing new is found". From b350521893c32bc1e2784cb4091c40350379dbde Mon Sep 17 00:00:00 2001 From: NewSoupVi <57900059+NewSoupVi@users.noreply.github.com> Date: Thu, 5 Sep 2024 22:21:51 +0200 Subject: [PATCH 20/27] Update docs/apworld_dev_faq.md Co-authored-by: qwint --- docs/apworld_dev_faq.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/apworld_dev_faq.md b/docs/apworld_dev_faq.md index fb9114c76fee..1ec046ac1469 100644 --- a/docs/apworld_dev_faq.md +++ b/docs/apworld_dev_faq.md @@ -52,7 +52,7 @@ The world API document mentions indirect conditions and **when** you should use Region sweep (the algorithm that determines which regions are reachable) is a Breadth-First Search of the region graph from the origin region, checking entrances one by one and adding newly reached nodes (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 entrance access conditions depend on regions, then it is possible for this to happen: +For performance reasons, AP only checks every entrance once. However, if an entrance's access condition depends on regions, then it is possible for this to happen: 1. An entrance that depends on a region is checked and determined to be nontraversable because the region hasn't been reached yet during the graph search. 2. After that, the region is reached by the graph search. From 5a09296f89568cf5fe42b0c25525ed715eafedc4 Mon Sep 17 00:00:00 2001 From: qwint Date: Fri, 29 Nov 2024 21:55:19 -0600 Subject: [PATCH 21/27] fix the last couple of wording issues I have with the indirect condition section to apworld dev faq doc --- docs/apworld_dev_faq.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/apworld_dev_faq.md b/docs/apworld_dev_faq.md index 1ec046ac1469..18122e73e356 100644 --- a/docs/apworld_dev_faq.md +++ b/docs/apworld_dev_faq.md @@ -48,11 +48,11 @@ item_pool += [self.create_filler() for _ in range(total_locations - len(item_poo ### 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 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. +The world API document mentions registering indirect conditions using multiworld.register_indirect_condition() 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 from the origin region, checking entrances one by one and adding newly reached nodes (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 condition depends on regions, then it is possible for this to happen: +For performance reasons, AP only checks every entrance once. However, if any entrance's access_rule depends on region access, then it is possible for this to happen: 1. An entrance that depends on a region is checked and determined to be nontraversable because the region hasn't been reached yet during the graph search. 2. After that, the region is reached by the graph search. From c90ddf85895f2c38e9c268877db9c6ac93e6c771 Mon Sep 17 00:00:00 2001 From: qwint Date: Fri, 29 Nov 2024 22:02:30 -0600 Subject: [PATCH 22/27] I didn't like that wording --- docs/apworld_dev_faq.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/apworld_dev_faq.md b/docs/apworld_dev_faq.md index 18122e73e356..5f10b78aebe9 100644 --- a/docs/apworld_dev_faq.md +++ b/docs/apworld_dev_faq.md @@ -48,7 +48,7 @@ item_pool += [self.create_filler() for _ in range(total_locations - len(item_poo ### 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 registering indirect conditions using multiworld.register_indirect_condition() and **when** you should use them, but not *how* they work and *why* they are necessary. This is because the explanation is quite complicated. +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 from the origin region, checking entrances one by one and adding newly reached nodes (regions) and their entrances to the queue until there is nothing more to check. From 2da8ce89a514ada505f3543e9a90a6e03507425f Mon Sep 17 00:00:00 2001 From: qwint Date: Thu, 5 Dec 2024 13:32:56 -0600 Subject: [PATCH 23/27] Apply suggestions from code review Co-authored-by: Scipio Wright --- docs/apworld_dev_faq.md | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/docs/apworld_dev_faq.md b/docs/apworld_dev_faq.md index 5f10b78aebe9..2af0da7d6189 100644 --- a/docs/apworld_dev_faq.md +++ b/docs/apworld_dev_faq.md @@ -50,19 +50,19 @@ item_pool += [self.create_filler() for _ in range(total_locations - len(item_poo 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 from the origin region, checking entrances one by one and adding newly reached nodes (regions) and their entrances to the queue until there is nothing more to check. +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 any entrance's access_rule depends on region access, then it is possible for this to happen: -1. An entrance that depends on a region is checked and determined to be nontraversable because the region hasn't been reached yet during the graph search. -2. After that, the region is reached by the graph search. +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. The entrance *would* now be determined to be traversable if it were rechecked, but it is not. 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. However, there is a way to **manually** define that a *specific* entrance needs to be rechecked during region sweep if a *specific* region is reached during it. This is what an indirect condition is. This keeps almost all of the performance upsides. Even a game making heavy use of indirect conditions (See: The Witness) is still significantly faster than if it just blanket "rechecked all entrances until nothing new is found". -The reason entrance access rules using `location.can_reach` and `entrance.can_reach` are also affected is simple: They call `region.can_reach` on their respective parent/source region. +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 also possible for a world to opt out of indirect conditions entirely, although it does come at a flat performance cost. -It should only be used by games that *really* need it. For most games, it should be reasonable to know all entrance → region dependencies, and in this case, indirect conditions are still preferred because they are faster. +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. From 8296621b1573af8f16bf1d62ee8f57efc904e7cc Mon Sep 17 00:00:00 2001 From: qwint Date: Thu, 5 Dec 2024 17:26:33 -0600 Subject: [PATCH 24/27] Apply suggestions from code review Co-authored-by: Scipio Wright --- docs/apworld_dev_faq.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/apworld_dev_faq.md b/docs/apworld_dev_faq.md index 2af0da7d6189..559c351cf44d 100644 --- a/docs/apworld_dev_faq.md +++ b/docs/apworld_dev_faq.md @@ -60,9 +60,9 @@ The entrance *would* now be determined to be traversable if it were rechecked, b 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. However, there is a way to **manually** define that a *specific* entrance needs to be rechecked during region sweep if a *specific* region is reached during it. This is what an indirect condition is. -This keeps almost all of the performance upsides. Even a game making heavy use of indirect conditions (See: The Witness) is still significantly faster than if it just blanket "rechecked all entrances until nothing new is found". +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 also possible for a world to opt out of indirect conditions entirely, although it does come at a flat performance cost. +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. From 7f61f87ffd8a8d9958a6d90e902da8c72196fb70 Mon Sep 17 00:00:00 2001 From: qwint Date: Fri, 6 Dec 2024 10:27:11 -0600 Subject: [PATCH 25/27] Update docs/apworld_dev_faq.md Co-authored-by: Scipio Wright --- docs/apworld_dev_faq.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/apworld_dev_faq.md b/docs/apworld_dev_faq.md index 559c351cf44d..8a21814c2167 100644 --- a/docs/apworld_dev_faq.md +++ b/docs/apworld_dev_faq.md @@ -56,7 +56,7 @@ For performance reasons, AP only checks every entrance once. However, if an entr 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. -The entrance *would* now be determined to be traversable if it were rechecked, but it is not. +This entrance *would* be called reachable 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. However, there is a way to **manually** define that a *specific* entrance needs to be rechecked during region sweep if a *specific* region is reached during it. This is what an indirect condition is. From a9e9c58861260811777ec45c2638077e286bb10e Mon Sep 17 00:00:00 2001 From: qwint Date: Fri, 6 Dec 2024 10:28:51 -0600 Subject: [PATCH 26/27] Update docs/apworld_dev_faq.md --- docs/apworld_dev_faq.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/apworld_dev_faq.md b/docs/apworld_dev_faq.md index 8a21814c2167..eead0e218f4c 100644 --- a/docs/apworld_dev_faq.md +++ b/docs/apworld_dev_faq.md @@ -56,7 +56,7 @@ For performance reasons, AP only checks every entrance once. However, if an entr 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 called reachable if it were rechecked, but it won't be rechecked this cycle. +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. However, there is a way to **manually** define that a *specific* entrance needs to be rechecked during region sweep if a *specific* region is reached during it. This is what an indirect condition is. From b15179440a49fbb9f2d93880e94d8bc3dbdc3552 Mon Sep 17 00:00:00 2001 From: qwint Date: Fri, 6 Dec 2024 10:32:50 -0600 Subject: [PATCH 27/27] Update docs/apworld_dev_faq.md Co-authored-by: Scipio Wright --- docs/apworld_dev_faq.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/apworld_dev_faq.md b/docs/apworld_dev_faq.md index eead0e218f4c..769a2fb3a0a7 100644 --- a/docs/apworld_dev_faq.md +++ b/docs/apworld_dev_faq.md @@ -59,7 +59,7 @@ For performance reasons, AP only checks every entrance once. However, if an entr 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. -However, there is a way to **manually** define that a *specific* entrance needs to be rechecked during region sweep if a *specific* region is reached during it. This is what an indirect condition is. +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.