Merge branch 'OverworldShuffleDev' into OverworldShuffle
This commit is contained in:
@@ -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]
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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 = {}
|
||||||
|
|||||||
@@ -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
2
Rom.py
@@ -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):
|
||||||
|
|||||||
16
Utils.py
16
Utils.py
@@ -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)
|
||||||
|
|||||||
@@ -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.
Reference in New Issue
Block a user