Add an extra pass to get correct spheres after culling

For an example of a circumstance in which the existing code produces
incorrect spheres, consider the following item locations in the vanilla
entrance layout:

* byrna in sphere 0
* hammer in sphere 0
* gloves in sphere 0
* bottle in sphere 0
* bow in spike cave (sphere 1)
* cape in hype cave (sphere 1)
* flippers on bumper cave Ledge (sphere 2)
* lastly both Swamp and PoD are pendants.

Well the culling phase will remove Byrna, because cape is good enough to
still get the bow. But now the bow in sphere 1 depends on the cape also
from sphere 1.
This commit is contained in:
Kevin Cathcart 2018-01-06 14:25:49 -05:00
parent 9846f924d2
commit a86573d529
1 changed files with 25 additions and 2 deletions

27
Main.py
View File

@ -232,8 +232,31 @@ def create_playthrough(world):
for location in to_delete:
sphere.remove(location)
# we are now down to just the required progress items in collection_spheres in a minimum number of spheres. As a cleanup, we right trim empty spheres (can happen if we have multiple triforces)
collection_spheres = [sphere for sphere in collection_spheres if sphere]
# we are now down to just the required progress items in collection_spheres. Unfortunately
# the previous pruning stage could potentially have made certain items dependant on others
# in the same or later sphere (because the location had 2 ways to access but the item originally
# used to access it was deemed not required.) So we need to do one final sphere collection pass
# to build up the correct spheres
required_locations = [item for sphere in collection_spheres for item in sphere]
state = CollectionState(world)
collection_spheres = []
while required_locations:
if not world.keysanity:
state.sweep_for_events(key_only=True)
sphere = list(filter(state.can_reach, required_locations))
for location in sphere:
required_locations.remove(location)
state.collect(location.item, True, location)
collection_spheres.append(sphere)
logging.getLogger('').debug('Calculated final sphere %i, containing %i of %i progress items.', len(collection_spheres), len(sphere), len(required_locations))
if not sphere:
raise RuntimeError('Not all required items reachable. Something went terribly wrong here.')
# store the required locations for statistical analysis
old_world.required_locations = [location.name for sphere in collection_spheres for location in sphere]