diff --git a/BaseClasses.py b/BaseClasses.py index 0c2925e5..6e1ebd41 100644 --- a/BaseClasses.py +++ b/BaseClasses.py @@ -1538,6 +1538,11 @@ class Region(object): self.crystal_switch = False def can_reach(self, state): + from Utils import stack_size3a + from DungeonGenerator import GenerationException + if stack_size3a() > 500: + raise GenerationException(f'Infinite loop detected for "{self.name}" located at \'Region.can_reach\'') + if state.stale[self.player]: state.update_reachable_regions(self.player) return self in state.reachable_regions[self.player] diff --git a/OverworldShuffle.py b/OverworldShuffle.py index 593e5a7c..43495139 100644 --- a/OverworldShuffle.py +++ b/OverworldShuffle.py @@ -908,6 +908,9 @@ def build_accessible_region_list(world, start_region, player, build_copy_world=F from Items import ItemFactory def explore_region(region_name, region=None): + if stack_size3a() > 500: + raise GenerationException(f'Infinite loop detected for "{start_region}" located at \'build_accessible_region_list\'') + explored_regions.append(region_name) if not region: region = base_world.get_region(region_name, player) diff --git a/Utils.py b/Utils.py index deed090d..99702a98 100644 --- a/Utils.py +++ b/Utils.py @@ -7,6 +7,7 @@ import sys import xml.etree.ElementTree as ET from collections import defaultdict from functools import reduce +from itertools import count def int16_as_bytes(value): @@ -674,6 +675,21 @@ def extract_data_from_jp_rom(rom): print() +def stack_size3a(size=2): + # See reference: https://stackoverflow.com/questions/34115298/how-do-i-get-the-current-depth-of-the-python-interpreter-stack + """Get stack size for caller's frame.""" + frame = sys._getframe(size) + try: + for size in count(size, 8): + frame = frame.f_back.f_back.f_back.f_back.\ + f_back.f_back.f_back.f_back + except AttributeError: + while frame: + frame = frame.f_back + size += 1 + return size - 1 + + class bidict(dict): def __init__(self, *args, **kwargs): super(bidict, self).__init__(*args, **kwargs)