Optimize fulfills_accessibility by pruning to relevant locations
This commit is contained in:
parent
32c5ee53e5
commit
c0cdeef67a
|
@ -416,7 +416,7 @@ class World(object):
|
||||||
else:
|
else:
|
||||||
return all((self.has_beaten_game(state, p) for p in range(1, self.players + 1)))
|
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 starting_state:
|
||||||
if self.has_beaten_game(starting_state):
|
if self.has_beaten_game(starting_state):
|
||||||
return True
|
return True
|
||||||
|
@ -448,42 +448,38 @@ class World(object):
|
||||||
|
|
||||||
return False
|
return False
|
||||||
|
|
||||||
def fulfills_accessibility(self):
|
def fulfills_accessibility(self, state: Optional[CollectionState] = None):
|
||||||
state = CollectionState(self)
|
"""Check if accessibility rules are fulfilled with current or supplied state."""
|
||||||
locations = {location for location in self.get_locations() if location.item}
|
if not state:
|
||||||
beatable_players = set()
|
state = CollectionState(self)
|
||||||
items_players = set()
|
players = {}
|
||||||
locations_players = set()
|
for player, access in self.accessibility.items():
|
||||||
for player in self.player_ids:
|
players.setdefault(access, set()).add(player)
|
||||||
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}")
|
|
||||||
|
|
||||||
beatable_fulfilled = False
|
beatable_fulfilled = False
|
||||||
|
|
||||||
def location_conditition(location : Location):
|
def location_conditition(location : Location):
|
||||||
"""Determine if this location has to be accessible"""
|
"""Determine if this location has to be accessible, location is already filtered by location_relevant"""
|
||||||
if location.player in locations_players:
|
if location.player in players["none"]:
|
||||||
return True
|
return False
|
||||||
elif location.player in items_players:
|
return True
|
||||||
return location.item.advancement or location.event
|
|
||||||
|
|
||||||
|
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
|
return False
|
||||||
|
|
||||||
def all_done():
|
def all_done():
|
||||||
"""Check if all access rules are fulfilled"""
|
"""Check if all access rules are fulfilled"""
|
||||||
if beatable_fulfilled:
|
if beatable_fulfilled:
|
||||||
for location in locations:
|
if any(location_conditition(location) for location in locations):
|
||||||
if location_conditition(location):
|
return False # still locations required to be collected
|
||||||
return False
|
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
locations = {location for location in self.get_locations() if location_relevant(location)}
|
||||||
|
|
||||||
while locations:
|
while locations:
|
||||||
sphere = set()
|
sphere = set()
|
||||||
for location in locations:
|
for location in locations:
|
||||||
|
@ -507,6 +503,7 @@ class World(object):
|
||||||
|
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
|
||||||
class CollectionState(object):
|
class CollectionState(object):
|
||||||
|
|
||||||
def __init__(self, parent: World):
|
def __init__(self, parent: World):
|
||||||
|
|
Loading…
Reference in New Issue