Core: cull events from multidata spheres (#3623)

Co-authored-by: Doug Hoskisson <beauxq@users.noreply.github.com>
This commit is contained in:
Fabian Dill 2024-11-30 04:11:03 +01:00 committed by GitHub
parent 0705f6e6c0
commit c1b27f79ac
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 45 additions and 3 deletions

View File

@ -604,6 +604,49 @@ class MultiWorld():
state.collect(location.item, True, location) state.collect(location.item, True, location)
locations -= sphere locations -= sphere
def get_sendable_spheres(self) -> Iterator[Set[Location]]:
"""
yields a set of multiserver sendable locations (location.item.code: int) for each logical sphere
If there are unreachable locations, the last sphere of reachable locations is followed by an empty set,
and then a set of all of the unreachable locations.
"""
state = CollectionState(self)
locations: Set[Location] = set()
events: Set[Location] = set()
for location in self.get_filled_locations():
if type(location.item.code) is int:
locations.add(location)
else:
events.add(location)
while locations:
sphere: Set[Location] = set()
# cull events out
done_events: Set[Union[Location, None]] = {None}
while done_events:
done_events = set()
for event in events:
if event.can_reach(state):
state.collect(event.item, True, event)
done_events.add(event)
events -= done_events
for location in locations:
if location.can_reach(state):
sphere.add(location)
yield sphere
if not sphere:
if locations:
yield locations # unreachable locations
break
for location in sphere:
state.collect(location.item, True, location)
locations -= sphere
def fulfills_accessibility(self, state: Optional[CollectionState] = None): def fulfills_accessibility(self, state: Optional[CollectionState] = None):
"""Check if accessibility rules are fulfilled with current or supplied state.""" """Check if accessibility rules are fulfilled with current or supplied state."""
if not state: if not state:

View File

@ -306,11 +306,10 @@ def main(args, seed=None, baked_server_options: Optional[Dict[str, object]] = No
# get spheres -> filter address==None -> skip empty # get spheres -> filter address==None -> skip empty
spheres: List[Dict[int, Set[int]]] = [] spheres: List[Dict[int, Set[int]]] = []
for sphere in multiworld.get_spheres(): for sphere in multiworld.get_sendable_spheres():
current_sphere: Dict[int, Set[int]] = collections.defaultdict(set) current_sphere: Dict[int, Set[int]] = collections.defaultdict(set)
for sphere_location in sphere: for sphere_location in sphere:
if type(sphere_location.address) is int: current_sphere[sphere_location.player].add(sphere_location.address)
current_sphere[sphere_location.player].add(sphere_location.address)
if current_sphere: if current_sphere:
spheres.append(dict(current_sphere)) spheres.append(dict(current_sphere))