Skip to content

Commit

Permalink
Remove the State region_cache.
Browse files Browse the repository at this point in the history
  • Loading branch information
Zannick committed Aug 20, 2019
1 parent 7c5bd0e commit 0137942
Show file tree
Hide file tree
Showing 5 changed files with 4 additions and 69 deletions.
1 change: 0 additions & 1 deletion Entrance.py
Expand Up @@ -9,7 +9,6 @@ def __init__(self, name='', parent=None):
self.world = parent.world
self.connected_region = None
self.spot_type = 'Entrance'
self.recursion_count = { 'child': 0, 'adult': 0 }
self.access_rule = lambda state, **kwargs: True
self.access_rules = []
self.reverse = None
Expand Down
3 changes: 0 additions & 3 deletions Fill.py
Expand Up @@ -198,9 +198,6 @@ def fill_dungeons_restrictive(window, worlds, playthrough, shuffled_locations, d
# place dungeon items
fill_restrictive(window, worlds, base_playthrough, shuffled_locations, dungeon_items)

for world in worlds:
world.state.clear_cached_unreachable()


# Places items into dungeon locations. This is used when there should be exactly
# one progression item per dungeon. This should be ran before all the progression
Expand Down
3 changes: 0 additions & 3 deletions Location.py
Expand Up @@ -15,7 +15,6 @@ def __init__(self, name='', address=None, address2=None, default=None, type='Che
self.type = type
self.scene = scene
self.spot_type = 'Location'
self.recursion_count = { 'child': 0, 'adult': 0 }
self.staleness_count = 0
self.access_rule = lambda state, **kwargs: True
self.access_rules = []
Expand Down Expand Up @@ -80,8 +79,6 @@ def can_reach(self, state, age=None, tod=TimeOfDay.NONE):


def can_reach_simple(self, state, age=None):
# todo: raw evaluation of access_rule? requires nonrecursive tod checks in state
# and GS Token and Gossip Stone Fairy have special checks as well
return self.access_rule(state, age=age, spot=self)


Expand Down
1 change: 0 additions & 1 deletion Region.py
Expand Up @@ -36,7 +36,6 @@ def __init__(self, name, type=RegionType.Overworld):
self.world = None
self.hint = None
self.spot_type = 'Region'
self.recursion_count = { 'child': 0, 'adult': 0 }
self.price = None
self.world = None
self.time_passes = False
Expand Down
65 changes: 4 additions & 61 deletions State.py
Expand Up @@ -13,8 +13,6 @@ class State(object):
def __init__(self, parent):
self.prog_items = Counter()
self.world = parent
self.region_cache = { 'child': {}, 'adult': {} }
self.recursion_count = { 'child': 0, 'adult': 0 }
self.playthrough = None


Expand All @@ -24,22 +22,11 @@ def is_glitched(self):
return self.world.logic_rules != 'glitchless'


def clear_cached_unreachable(self):
# we only need to invalidate results which were False, places we could reach before we can still reach after adding more items
for cache_type in self.region_cache:
self.region_cache[cache_type] = {k: v for k, v in self.region_cache[cache_type].items() if v}


def clear_cache(self):
self.region_cache = { 'child': {}, 'adult': {} }


def copy(self, new_world=None):
if not new_world:
new_world = self.world
new_state = State(new_world)
new_state.prog_items = copy.copy(self.prog_items)
new_state.region_cache = {k: copy.copy(v) for k,v in self.region_cache.items()}
return new_state


Expand Down Expand Up @@ -73,40 +60,12 @@ def can_reach(self, spot=None, resolution_hint='Region', tod=TimeOfDay.NONE, age
if not isinstance(spot, Region):
return spot.can_reach(self, age=age, tod=tod)

# At this point, we're looking to verify access to the region at a specific age and time.
# If we have a playthrough (we do), it should already be able to tell us fast if we have access.
# We can also be confident when it says no, since otherwise this recursion would
# find a path the playthrough should have found.
return self.playthrough.can_reach(spot, age=age, tod=tod)

# If we are currently checking for reachability with a specific time of day and the needed time can be obtained here,
# we want to continue the reachability test without a time of day, to make sure we could actually get there
if tod != None and self.can_provide_time(spot, tod):
return spot.can_reach(self, age=age)

# If we reached this point, it means the current age should be used
if spot.recursion_count[age] > 0:
return False

# Normal caches can't be used while checking for reachability with a specific time of day
if tod == None:
if self.playthrough != None and self.playthrough.can_reach(spot, age=age):
return True

if spot in self.region_cache[age]:
return self.region_cache[age][spot]

# for the purpose of evaluating results, recursion is resolved by always denying recursive access (as that is what we are trying to figure out right now in the first place
spot.recursion_count[age] += 1
self.recursion_count[age] += 1

can_reach = spot.can_reach(self, age=age, tod=tod)

spot.recursion_count[age] -= 1
self.recursion_count[age] -= 1

# we store true results and qualified false results (i.e. ones not inside a hypothetical)
if tod == None and (can_reach or self.recursion_count[age] == 0):
self.region_cache[age][spot] = can_reach

return can_reach


def as_both(self, spot, tod=TimeOfDay.NONE):
if self.can_become_adult() and self.can_become_child():
Expand All @@ -121,15 +80,6 @@ def as_age(self, spot, age, tod=TimeOfDay.NONE):
return False


def can_provide_time(self, region, provide_tod):
if region.time_passes:
return True
# Ganon's Castle Grounds is a special scene that forces time to be the start of the night (aka dampe's time)
if region.name == 'Ganons Castle Grounds':
return provide_tod == 'dampe'
return False


def item_name(self, location):
location = self.world.get_location(location)
if location.item is None:
Expand Down Expand Up @@ -485,7 +435,6 @@ def can_live_dmg(self, hearts):
def collect(self, item):
if item.advancement:
self.prog_items[item.name] += 1
self.clear_cached_unreachable()


# Be careful using this function. It will not uncollect any
Expand All @@ -496,12 +445,6 @@ def remove(self, item):
if self.prog_items[item.name] <= 0:
del self.prog_items[item.name]

# invalidate collected cache. unreachable regions are still unreachable
for cache_type in self.region_cache:
self.region_cache[cache_type] = {k: v for k, v in self.region_cache[cache_type].items() if not v}

self.recursion_count = {k: 0 for k in self.recursion_count}


def __getstate__(self):
return self.__dict__.copy()
Expand Down

0 comments on commit 0137942

Please sign in to comment.