Merge branch 'OverworldShuffleDev' into OverworldShuffle

This commit is contained in:
codemann8
2021-12-24 16:00:50 -06:00
8 changed files with 50 additions and 14 deletions

View File

@@ -1538,6 +1538,11 @@ class Region(object):
self.crystal_switch = False self.crystal_switch = False
def can_reach(self, state): 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]: if state.stale[self.player]:
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]

View File

@@ -1,5 +1,10 @@
# Changelog # Changelog
### 0.2.3.5
- Fixed issue with multiworld generation
- Added infinite loop detection
- Move mirror portal off screen during mirror bonk in Crossed OW
### 0.2.3.4 ### 0.2.3.4
- Fixed major issue with subsequent seeds using same seed/settings resulting different - Fixed major issue with subsequent seeds using same seed/settings resulting different
- Flute Shuffle now awards separated regions a prorated number of flute spots based on size - Flute Shuffle now awards separated regions a prorated number of flute spots based on size

View File

@@ -40,9 +40,9 @@ def link_entrances(world, player):
connect_simple(world, 'Other World S&Q', 'Pyramid Area', player) connect_simple(world, 'Other World S&Q', 'Pyramid Area', player)
else: else:
entrance_pool.remove('Pyramid Hole') entrance_pool.remove('Pyramid Hole')
entrance_pool.add('Inverted Pyramid Hole') entrance_pool.append('Inverted Pyramid Hole')
entrance_pool.remove('Pyramid Entrance') entrance_pool.remove('Pyramid Entrance')
entrance_pool.add('Inverted Pyramid Entrance') entrance_pool.append('Inverted Pyramid Entrance')
drop_connections.append(tuple(('Inverted Pyramid Hole', 'Pyramid'))) drop_connections.append(tuple(('Inverted Pyramid Hole', 'Pyramid')))
dropexit_connections.append(tuple(('Inverted Pyramid Entrance', 'Pyramid Exit'))) dropexit_connections.append(tuple(('Inverted Pyramid Entrance', 'Pyramid Exit')))
connect_simple(world, 'Other World S&Q', 'Hyrule Castle Ledge', player) connect_simple(world, 'Other World S&Q', 'Hyrule Castle Ledge', player)
@@ -1476,8 +1476,8 @@ def junk_fill_inaccessible(world, player):
from DoorShuffle import find_inaccessible_regions from DoorShuffle import find_inaccessible_regions
find_inaccessible_regions(world, player) find_inaccessible_regions(world, player)
for player in range(1, world.players + 1): for p in range(1, world.players + 1):
world.key_logic[player] = {} world.key_logic[p] = {}
base_world = copy_world(world) base_world = copy_world(world)
base_world.override_bomb_check = True base_world.override_bomb_check = True
world.key_logic = {} world.key_logic = {}
@@ -1641,8 +1641,8 @@ def build_accessible_entrance_list(world, start_region, player, assumed_inventor
from Main import copy_world from Main import copy_world
from Items import ItemFactory from Items import ItemFactory
for player in range(1, world.players + 1): for p in range(1, world.players + 1):
world.key_logic[player] = {} world.key_logic[p] = {}
base_world = copy_world(world) base_world = copy_world(world)
base_world.override_bomb_check = True base_world.override_bomb_check = True
world.key_logic = {} world.key_logic = {}
@@ -1751,8 +1751,8 @@ def can_reach(world, entrance_name, region_name, player):
from Items import ItemFactory from Items import ItemFactory
from DoorShuffle import find_inaccessible_regions from DoorShuffle import find_inaccessible_regions
for player in range(1, world.players + 1): for p in range(1, world.players + 1):
world.key_logic[player] = {} world.key_logic[p] = {}
base_world = copy_world(world) base_world = copy_world(world)
base_world.override_bomb_check = True base_world.override_bomb_check = True
world.key_logic = {} world.key_logic = {}

View File

@@ -4,7 +4,7 @@ from BaseClasses import OWEdge, WorldType, RegionType, Direction, Terrain, PolSl
from Regions import mark_dark_world_regions, mark_light_world_regions from Regions import mark_dark_world_regions, mark_light_world_regions
from OWEdges import OWTileRegions, OWTileGroups, OWEdgeGroups, OWExitTypes, OpenStd, parallel_links, IsParallel from OWEdges import OWTileRegions, OWTileGroups, OWEdgeGroups, OWExitTypes, OpenStd, parallel_links, IsParallel
__version__ = '0.2.3.4-u' __version__ = '0.2.3.5-u'
def link_overworld(world, player): def link_overworld(world, player):
# setup mandatory connections # setup mandatory connections
@@ -853,8 +853,8 @@ def build_sectors(world, player):
from OWEdges import OWTileRegions from OWEdges import OWTileRegions
# perform accessibility check on duplicate world # perform accessibility check on duplicate world
for player in range(1, world.players + 1): for p in range(1, world.players + 1):
world.key_logic[player] = {} world.key_logic[p] = {}
base_world = copy_world(world) base_world = copy_world(world)
world.key_logic = {} world.key_logic = {}
@@ -906,8 +906,12 @@ def build_accessible_region_list(world, start_region, player, build_copy_world=F
from Main import copy_world from Main import copy_world
from BaseClasses import CollectionState from BaseClasses import CollectionState
from Items import ItemFactory from Items import ItemFactory
from Utils import stack_size3a
def explore_region(region_name, region=None): 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) explored_regions.append(region_name)
if not region: if not region:
region = base_world.get_region(region_name, player) region = base_world.get_region(region_name, player)
@@ -925,8 +929,8 @@ def build_accessible_region_list(world, start_region, player, build_copy_world=F
explore_region(exit.connected_region.name, exit.connected_region) explore_region(exit.connected_region.name, exit.connected_region)
if build_copy_world: if build_copy_world:
for player in range(1, world.players + 1): for p in range(1, world.players + 1):
world.key_logic[player] = {} world.key_logic[p] = {}
base_world = copy_world(world) base_world = copy_world(world)
base_world.override_bomb_check = True base_world.override_bomb_check = True
world.key_logic = {} world.key_logic = {}

2
Rom.py
View File

@@ -33,7 +33,7 @@ from source.classes.SFX import randomize_sfx
JAP10HASH = '03a63945398191337e896e5771f77173' JAP10HASH = '03a63945398191337e896e5771f77173'
RANDOMIZERBASEHASH = 'c5903112ffe302d1e9a3878ee720d1b3' RANDOMIZERBASEHASH = 'c1a00c60144c6cc5a6ef5f00617a9b38'
class JsonRom(object): class JsonRom(object):

View File

@@ -7,6 +7,7 @@ import sys
import xml.etree.ElementTree as ET import xml.etree.ElementTree as ET
from collections import defaultdict from collections import defaultdict
from functools import reduce from functools import reduce
from itertools import count
def int16_as_bytes(value): def int16_as_bytes(value):
@@ -674,6 +675,21 @@ def extract_data_from_jp_rom(rom):
print() 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): class bidict(dict):
def __init__(self, *args, **kwargs): def __init__(self, *args, **kwargs):
super(bidict, self).__init__(*args, **kwargs) super(bidict, self).__init__(*args, **kwargs)

View File

@@ -160,6 +160,12 @@ OWPreserveMirrorSprite:
pla : lda #$de : pha ; in vanilla, if in dark world, jump to $05afdf pla : lda #$de : pha ; in vanilla, if in dark world, jump to $05afdf
rtl rtl
} }
OWMirrorSpriteMove:
{
lda.l OWMode+1 : and.b #!FLAG_OW_CROSSED : beq +
lda $1acf : eor #$80 : sta $1acf
+ lda #$2c : jml.l $07A985 ; what we wrote over
}
OWFluteCancel: OWFluteCancel:
{ {

Binary file not shown.