some speed improvments

This commit is contained in:
Fabian Dill 2020-03-07 23:20:11 +01:00
parent 1d75d5b70e
commit 27b6dd8bd7
1 changed files with 28 additions and 22 deletions

View File

@ -8,6 +8,7 @@ from collections import OrderedDict
from collections_extended import bag from collections_extended import bag
from EntranceShuffle import door_addresses from EntranceShuffle import door_addresses
from Utils import int16_as_bytes from Utils import int16_as_bytes
from typing import Union
class World(object): class World(object):
player_names: list player_names: list
@ -294,7 +295,7 @@ class World(object):
return False return False
def has_beaten_game(self, state, player=None): def has_beaten_game(self, state, player: Union[None, int] = None):
if player: if player:
return state.has('Triforce', player) return state.has('Triforce', player)
else: else:
@ -302,14 +303,15 @@ class World(object):
def can_beat_game(self, starting_state=None): def can_beat_game(self, starting_state=None):
if starting_state: if starting_state:
if self.has_beaten_game(starting_state):
return True
state = starting_state.copy() state = starting_state.copy()
else: else:
state = CollectionState(self) if self.has_beaten_game(self.state):
if self.has_beaten_game(state):
return True return True
state = CollectionState(self)
prog_locations = [location for location in self.get_locations() if location.item is not None and (location.item.advancement or location.event) and location not in state.locations_checked] prog_locations = {location for location in self.get_locations() if location.item is not None and (
location.item.advancement or location.event) and location not in state.locations_checked}
while prog_locations: while prog_locations:
sphere = [] sphere = []
@ -343,6 +345,7 @@ class CollectionState(object):
self.stale = {player: True for player in range(1, parent.players + 1)} self.stale = {player: True for player in range(1, parent.players + 1)}
for item in parent.precollected_items: for item in parent.precollected_items:
self.collect(item, True) self.collect(item, True)
self._reachable_cache = set()
def update_reachable_regions(self, player: int): def update_reachable_regions(self, player: int):
player_regions = self.world.get_regions(player) player_regions = self.world.get_regions(player)
@ -369,9 +372,10 @@ class CollectionState(object):
return ret return ret
def can_reach(self, spot, resolution_hint=None, player=None): def can_reach(self, spot, resolution_hint=None, player=None):
try: if (player, getattr(spot, "name", spot)) in self._reachable_cache:
spot_type = spot.spot_type return True
except AttributeError: else:
if not hasattr(spot, "spot_type"):
# try to resolve a name # try to resolve a name
if resolution_hint == 'Location': if resolution_hint == 'Location':
spot = self.world.get_location(spot, player) spot = self.world.get_location(spot, player)
@ -380,7 +384,9 @@ class CollectionState(object):
else: else:
# default to Region # default to Region
spot = self.world.get_region(spot, player) spot = self.world.get_region(spot, player)
res = spot.can_reach(self)
if res:
self._reachable_cache.add((player, spot.name))
return spot.can_reach(self) return spot.can_reach(self)
def sweep_for_events(self, key_only=False, locations=None): def sweep_for_events(self, key_only=False, locations=None):
@ -707,7 +713,7 @@ class Region(object):
state.update_reachable_regions(self.player) state.update_reachable_regions(self.player)
return self in state.reachable_regions[self.player] return self in state.reachable_regions[self.player]
def can_reach_private(self, state): def can_reach_private(self, state: CollectionState):
for entrance in self.entrances: for entrance in self.entrances:
if entrance.can_reach(state): if entrance.can_reach(state):
if not self in state.path: if not self in state.path:
@ -715,7 +721,7 @@ class Region(object):
return True return True
return False return False
def can_fill(self, item): def can_fill(self, item: Item):
inside_dungeon_item = ((item.smallkey and not self.world.keyshuffle[item.player]) inside_dungeon_item = ((item.smallkey and not self.world.keyshuffle[item.player])
or (item.bigkey and not self.world.bigkeyshuffle[item.player]) or (item.bigkey and not self.world.bigkeyshuffle[item.player])
or (item.map and not self.world.mapshuffle[item.player]) or (item.map and not self.world.mapshuffle[item.player])