Optimize fulfills_accessibility by pruning to relevant locations

This commit is contained in:
Fabian Dill 2021-01-13 14:27:17 +01:00
parent 32c5ee53e5
commit c0cdeef67a
1 changed files with 22 additions and 25 deletions

View File

@ -416,7 +416,7 @@ class World(object):
else:
return all((self.has_beaten_game(state, p) for p in range(1, self.players + 1)))
def can_beat_game(self, starting_state=None):
def can_beat_game(self, starting_state : Optional[CollectionState]=None):
if starting_state:
if self.has_beaten_game(starting_state):
return True
@ -448,42 +448,38 @@ class World(object):
return False
def fulfills_accessibility(self):
state = CollectionState(self)
locations = {location for location in self.get_locations() if location.item}
beatable_players = set()
items_players = set()
locations_players = set()
for player in self.player_ids:
access = self.accessibility[player]
if access == "none":
beatable_players.add(player)
elif access == "items":
items_players.add(player)
elif access == "locations":
locations_players.add(player)
else:
raise Exception(f"unknown access rule {access} for player {player}")
def fulfills_accessibility(self, state: Optional[CollectionState] = None):
"""Check if accessibility rules are fulfilled with current or supplied state."""
if not state:
state = CollectionState(self)
players = {}
for player, access in self.accessibility.items():
players.setdefault(access, set()).add(player)
beatable_fulfilled = False
def location_conditition(location : Location):
"""Determine if this location has to be accessible"""
if location.player in locations_players:
return True
elif location.player in items_players:
return location.item.advancement or location.event
"""Determine if this location has to be accessible, location is already filtered by location_relevant"""
if location.player in players["none"]:
return False
return True
def location_relevant(location : Location):
"""Determine if this location is relevant to sweep."""
if location.player in players["locations"] or location.event or \
(location.item and location.item.advancement):
return True
return False
def all_done():
"""Check if all access rules are fulfilled"""
if beatable_fulfilled:
for location in locations:
if location_conditition(location):
return False
if any(location_conditition(location) for location in locations):
return False # still locations required to be collected
return True
locations = {location for location in self.get_locations() if location_relevant(location)}
while locations:
sphere = set()
for location in locations:
@ -507,6 +503,7 @@ class World(object):
return False
class CollectionState(object):
def __init__(self, parent: World):