Upgrades doors to be written out by the rom. (No testing today)
Added some various modes to play around with. Fixed prototype's generation code to run
This commit is contained in:
@@ -8,9 +8,10 @@ from Utils import int16_as_bytes
|
|||||||
|
|
||||||
class World(object):
|
class World(object):
|
||||||
|
|
||||||
def __init__(self, players, shuffle, logic, mode, swords, difficulty, difficulty_adjustments, timer, progressive, goal, algorithm, place_dungeon_items, accessibility, shuffle_ganon, quickswap, fastmenu, disable_music, keysanity, retro, custom, customitemarray, boss_shuffle, hints):
|
def __init__(self, players, shuffle, doorShuffle, logic, mode, swords, difficulty, difficulty_adjustments, timer, progressive, goal, algorithm, place_dungeon_items, accessibility, shuffle_ganon, quickswap, fastmenu, disable_music, keysanity, retro, custom, customitemarray, boss_shuffle, hints):
|
||||||
self.players = players
|
self.players = players
|
||||||
self.shuffle = shuffle
|
self.shuffle = shuffle
|
||||||
|
self.doorShuffle = doorShuffle
|
||||||
self.logic = logic
|
self.logic = logic
|
||||||
self.mode = mode
|
self.mode = mode
|
||||||
self.swords = swords
|
self.swords = swords
|
||||||
@@ -811,23 +812,41 @@ class DoorType(Enum):
|
|||||||
|
|
||||||
@unique
|
@unique
|
||||||
class Direction(Enum):
|
class Direction(Enum):
|
||||||
North = 1
|
North = 0
|
||||||
West = 2
|
West = 1
|
||||||
South = 3
|
South = 2
|
||||||
East = 4
|
East = 3
|
||||||
|
|
||||||
|
|
||||||
class Door(object):
|
class Door(object):
|
||||||
def __init__(self, player, name, type, direction):
|
def __init__(self, player, name, type, direction, roomIndex, doorIndex, layer, toggle=False):
|
||||||
self.player = player
|
self.player = player
|
||||||
self.name = name
|
self.name = name
|
||||||
self.type = type
|
self.type = type
|
||||||
self.direction = direction
|
self.direction = direction
|
||||||
self.connected = False
|
|
||||||
|
# rom properties
|
||||||
|
self.roomIndex = roomIndex
|
||||||
|
self.doorIndex = doorIndex # 0,1,2 + Direction (N:0, W:3, S:6, E:9)
|
||||||
|
self.layer = layer # 0 for normal floor, 1 for the inset layer
|
||||||
|
self.toggle = toggle
|
||||||
|
|
||||||
|
# logical properties
|
||||||
|
# self.connected = False # combine with Dest?
|
||||||
|
self.dest = None
|
||||||
self.parentChunk = None
|
self.parentChunk = None
|
||||||
# probably need exact location of the 12 base types (6 intraroom doors)
|
self.blocked = False # Indicates if the door is normally blocked off. (Sanc door or always closed)
|
||||||
# need the z-index
|
self.smallKey = False # There's a small key door on this side
|
||||||
# need the room index it is located in most likely
|
self.bigKey = False # There's a big key door on this side
|
||||||
|
|
||||||
|
def getAddress(self):
|
||||||
|
if self.type == DoorType.Normal:
|
||||||
|
return 0x13A000 + self.roomIndex * 24 + (self.doorIndex + self.direction.value * 3) * 2
|
||||||
|
|
||||||
|
def getTarget(self, toggle):
|
||||||
|
layer = 4 * (self.layer ^ 1 if toggle else self.layer)
|
||||||
|
return [self.roomIndex, layer + self.doorIndex]
|
||||||
|
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
return str(self.__unicode__())
|
return str(self.__unicode__())
|
||||||
|
|||||||
225
DoorShuffle.py
225
DoorShuffle.py
@@ -9,8 +9,6 @@ from Items import ItemFactory
|
|||||||
|
|
||||||
def link_doors(world, player):
|
def link_doors(world, player):
|
||||||
|
|
||||||
logger = logging.getLogger('')
|
|
||||||
|
|
||||||
# Make drop-down connections - if applicable
|
# Make drop-down connections - if applicable
|
||||||
for exitName, regionName in mandatory_connections:
|
for exitName, regionName in mandatory_connections:
|
||||||
connect_simple_door(world, exitName, regionName, player)
|
connect_simple_door(world, exitName, regionName, player)
|
||||||
@@ -27,18 +25,34 @@ def link_doors(world, player):
|
|||||||
for exitName, regionName in dungeon_warps:
|
for exitName, regionName in dungeon_warps:
|
||||||
connect_simple_door(world, exitName, regionName, player)
|
connect_simple_door(world, exitName, regionName, player)
|
||||||
|
|
||||||
# vanilla - todo: different modes
|
if world.doorShuffle == 'vanilla':
|
||||||
for entrance, ext in default_door_connections:
|
for entrance, ext in default_door_connections:
|
||||||
connect_two_way(world, entrance, ext, player)
|
connect_two_way(world, entrance, ext, player)
|
||||||
for ent, ext in default_one_way_connections:
|
for ent, ext in default_one_way_connections:
|
||||||
connect_one_way(world, ent, ext, player)
|
connect_one_way(world, ent, ext, player)
|
||||||
|
normal_dungeon_pool(world, player)
|
||||||
|
elif world.doorShuffle == 'basic':
|
||||||
|
normal_dungeon_pool(world, player)
|
||||||
|
within_dungeon(world, player)
|
||||||
|
elif world.doorShuffle == 'crossed':
|
||||||
|
normal_dungeon_pool(world, player)
|
||||||
|
cross_dungeon(world, player)
|
||||||
|
elif world.doorShuffle == 'experimental':
|
||||||
|
normal_dungeon_pool(world, player)
|
||||||
|
experiment(world, player)
|
||||||
|
|
||||||
|
mark_regions(world, player)
|
||||||
|
|
||||||
|
|
||||||
|
def normal_dungeon_pool(world, player):
|
||||||
# vanilla dungeon items
|
# vanilla dungeon items
|
||||||
ES = world.get_dungeon('Hyrule Castle', player)
|
ES = world.get_dungeon('Hyrule Castle', player)
|
||||||
ES.small_keys = [ItemFactory('Small Key (Escape)', player)]
|
ES.small_keys = [ItemFactory('Small Key (Escape)', player)]
|
||||||
EP = world.get_dungeon('Eastern Palace', player)
|
EP = world.get_dungeon('Eastern Palace', player)
|
||||||
EP.big_key = ItemFactory('Big Key (Eastern Palace)', player)
|
EP.big_key = ItemFactory('Big Key (Eastern Palace)', player)
|
||||||
|
|
||||||
|
|
||||||
|
def mark_regions(world, player):
|
||||||
# traverse dungeons and make sure dungeon property is assigned
|
# traverse dungeons and make sure dungeon property is assigned
|
||||||
playerDungeons = [dungeon for dungeon in world.dungeons if dungeon.player == player]
|
playerDungeons = [dungeon for dungeon in world.dungeons if dungeon.player == player]
|
||||||
for dungeon in playerDungeons:
|
for dungeon in playerDungeons:
|
||||||
@@ -52,13 +66,84 @@ def link_doors(world, player):
|
|||||||
d = world.check_for_door(ext.name, player)
|
d = world.check_for_door(ext.name, player)
|
||||||
connected = ext.connected_region
|
connected = ext.connected_region
|
||||||
if d is not None and connected is not None:
|
if d is not None and connected is not None:
|
||||||
if d.connected and connected.name not in dungeon.regions and connected.type == RegionType.Dungeon and connected.name not in queue:
|
if d.dest is not None and connected.name not in dungeon.regions and connected.type == RegionType.Dungeon and connected.name not in queue:
|
||||||
queue.append(connected) # needs to be added
|
queue.append(connected) # needs to be added
|
||||||
elif connected is not None and connected.name not in dungeon.regions and connected.type == RegionType.Dungeon and connected.name not in queue:
|
elif connected is not None and connected.name not in dungeon.regions and connected.type == RegionType.Dungeon and connected.name not in queue:
|
||||||
queue.append(connected) # needs to be added
|
queue.append(connected) # needs to be added
|
||||||
return
|
|
||||||
|
|
||||||
#code below is a prototype for cross-dungeon mode
|
|
||||||
|
# some useful functions
|
||||||
|
def switch_dir(direction):
|
||||||
|
oppositemap = {
|
||||||
|
Direction.South: Direction.North,
|
||||||
|
Direction.North: Direction.South,
|
||||||
|
Direction.West: Direction.East,
|
||||||
|
Direction.East: Direction.West,
|
||||||
|
}
|
||||||
|
return oppositemap[direction]
|
||||||
|
|
||||||
|
|
||||||
|
def connect_simple_door(world, exit_name, region_name, player):
|
||||||
|
region = world.get_region(region_name, player)
|
||||||
|
world.get_entrance(exit_name, player).connect(region)
|
||||||
|
d = world.check_for_door(exit_name, player)
|
||||||
|
if d is not None:
|
||||||
|
d.dest = region
|
||||||
|
|
||||||
|
|
||||||
|
def connect_two_way(world, entrancename, exitname, player):
|
||||||
|
entrance = world.get_entrance(entrancename, player)
|
||||||
|
ext = world.get_entrance(exitname, player)
|
||||||
|
|
||||||
|
# if these were already connected somewhere, remove the backreference
|
||||||
|
if entrance.connected_region is not None:
|
||||||
|
entrance.connected_region.entrances.remove(entrance, player)
|
||||||
|
if ext.connected_region is not None:
|
||||||
|
ext.connected_region.entrances.remove(ext)
|
||||||
|
|
||||||
|
# todo - access rules for the doors...
|
||||||
|
entrance.connect(ext.parent_region)
|
||||||
|
ext.connect(entrance.parent_region)
|
||||||
|
if entrance.parent_region.dungeon:
|
||||||
|
ext.parent_region.dungeon = entrance.parent_region.dungeon
|
||||||
|
x = world.check_for_door(entrancename, player)
|
||||||
|
y = world.check_for_door(exitname, player)
|
||||||
|
if x is not None:
|
||||||
|
x.dest = y
|
||||||
|
if y is not None:
|
||||||
|
y.dest = x
|
||||||
|
# world.spoiler.set_entrance(entrance.name, exit.name, 'both') # todo: spoiler stuff
|
||||||
|
|
||||||
|
|
||||||
|
def connect_one_way(world, entrancename, exitname, player):
|
||||||
|
entrance = world.get_entrance(entrancename, player)
|
||||||
|
ext = world.get_entrance(exitname, player)
|
||||||
|
|
||||||
|
# if these were already connected somewhere, remove the backreference
|
||||||
|
if entrance.connected_region is not None:
|
||||||
|
entrance.connected_region.entrances.remove(entrance, player)
|
||||||
|
if ext.connected_region is not None:
|
||||||
|
ext.connected_region.entrances.remove(ext)
|
||||||
|
|
||||||
|
entrance.connect(ext.parent_region)
|
||||||
|
if entrance.parent_region.dungeon:
|
||||||
|
ext.parent_region.dungeon = entrance.parent_region.dungeon
|
||||||
|
x = world.check_for_door(entrancename, player)
|
||||||
|
y = world.check_for_door(exitname, player)
|
||||||
|
if x is not None:
|
||||||
|
x.dest = y
|
||||||
|
if y is not None:
|
||||||
|
y.dest = x
|
||||||
|
# spoiler info goes here?
|
||||||
|
|
||||||
|
|
||||||
|
def within_dungeon(world, player):
|
||||||
|
raise NotImplementedError('Haven\'t started this yet')
|
||||||
|
|
||||||
|
|
||||||
|
# code below is an early prototype for cross-dungeon mode
|
||||||
|
def cross_dungeon(world, player):
|
||||||
|
logger = logging.getLogger('')
|
||||||
|
|
||||||
# figure out which dungeons have open doors and which doors still need to be connected
|
# figure out which dungeons have open doors and which doors still need to be connected
|
||||||
|
|
||||||
@@ -79,15 +164,15 @@ def link_doors(world, player):
|
|||||||
available_doors = set(world.doors)
|
available_doors = set(world.doors)
|
||||||
|
|
||||||
unfinished_dungeons = []
|
unfinished_dungeons = []
|
||||||
# modfiy avail doors and d_regions, produces a list of unlinked doors
|
# modify avail doors and d_regions, produces a list of unlinked doors
|
||||||
for dungeon in world.dungeons:
|
for dungeon in world.dungeons:
|
||||||
dungeon.paths = dungeon_paths[dungeon.name]
|
dungeon.paths = dungeon_paths[dungeon.name]
|
||||||
for path in dungeon.paths:
|
for path in dungeon.paths:
|
||||||
dungeon.path_completion[path] = False
|
dungeon.path_completion[path] = False
|
||||||
for regionName in list(dungeon.regions):
|
for regionName in list(dungeon.regions):
|
||||||
region = world.get_region(regionName)
|
region = world.get_region(regionName, player)
|
||||||
dungeon.regions.remove(regionName)
|
dungeon.regions.remove(regionName)
|
||||||
chunk = create_chunk(world, region, available_dungeon_regions, available_doors)
|
chunk = create_chunk(world, player, region, available_dungeon_regions, available_doors)
|
||||||
dungeon.chunks.append(chunk)
|
dungeon.chunks.append(chunk)
|
||||||
# todo: indicate entrance chunks
|
# todo: indicate entrance chunks
|
||||||
dungeon.regions.extend(chunk.regions)
|
dungeon.regions.extend(chunk.regions)
|
||||||
@@ -108,7 +193,7 @@ def link_doors(world, player):
|
|||||||
avail_chunks = []
|
avail_chunks = []
|
||||||
while len(available_dungeon_regions) > 0:
|
while len(available_dungeon_regions) > 0:
|
||||||
region = available_dungeon_regions.pop()
|
region = available_dungeon_regions.pop()
|
||||||
chunk = create_chunk(world, region, available_dungeon_regions)
|
chunk = create_chunk(world, player, region, available_dungeon_regions)
|
||||||
if chunk.outflow > 0:
|
if chunk.outflow > 0:
|
||||||
avail_chunks.append(chunk)
|
avail_chunks.append(chunk)
|
||||||
|
|
||||||
@@ -126,11 +211,11 @@ def link_doors(world, player):
|
|||||||
for dungeon in unfinished_dungeons:
|
for dungeon in unfinished_dungeons:
|
||||||
logger.info('Starting %s', dungeon.name)
|
logger.info('Starting %s', dungeon.name)
|
||||||
bailcnt = 0
|
bailcnt = 0
|
||||||
while not is_dungeon_finished(world, dungeon):
|
while not is_dungeon_finished(world, player, dungeon):
|
||||||
# pick some unfinished criteria to help?
|
# pick some unfinished criteria to help?
|
||||||
trgt_pct = len(dungeon.regions) / target_regions
|
trgt_pct = len(dungeon.regions) / target_regions
|
||||||
for path in dungeon.paths:
|
for path in dungeon.paths:
|
||||||
find_path(world, path, dungeon.path_completion)
|
find_path(world, player, path, dungeon.path_completion)
|
||||||
|
|
||||||
# process - expand to about half size
|
# process - expand to about half size
|
||||||
# start closing off unlinked doors - self pick vs dead end pick
|
# start closing off unlinked doors - self pick vs dead end pick
|
||||||
@@ -187,14 +272,13 @@ def link_doors(world, player):
|
|||||||
else:
|
else:
|
||||||
bailcnt += 1
|
bailcnt += 1
|
||||||
|
|
||||||
if len(dungeon.unlinked_doors) == 0 and not is_dungeon_finished(world, dungeon):
|
if len(dungeon.unlinked_doors) == 0 and not is_dungeon_finished(world, player, dungeon):
|
||||||
raise RuntimeError('Made a bad dungeon - more smarts needed')
|
raise RuntimeError('Made a bad dungeon - more smarts needed')
|
||||||
if bailcnt > 100:
|
if bailcnt > 100:
|
||||||
raise RuntimeError('Infinite loop detected - see output')
|
raise RuntimeError('Infinite loop detected - see output')
|
||||||
|
|
||||||
|
|
||||||
|
def create_chunk(world, player, newregion, available_dungeon_regions, available_doors=None):
|
||||||
def create_chunk(world, newregion, available_dungeon_regions, available_doors=None):
|
|
||||||
# if newregion.name in dungeon.regions:
|
# if newregion.name in dungeon.regions:
|
||||||
# return # we've been here before
|
# return # we've been here before
|
||||||
chunk = RegionChunk()
|
chunk = RegionChunk()
|
||||||
@@ -206,14 +290,14 @@ def create_chunk(world, newregion, available_dungeon_regions, available_doors=No
|
|||||||
available_dungeon_regions.remove(region)
|
available_dungeon_regions.remove(region)
|
||||||
chunk.chests += len(region.locations)
|
chunk.chests += len(region.locations)
|
||||||
for ext in region.exits:
|
for ext in region.exits:
|
||||||
d = world.check_for_door(ext.name)
|
d = world.check_for_door(ext.name, player)
|
||||||
connected = ext.connected_region
|
connected = ext.connected_region
|
||||||
# todo - check for key restrictions?
|
# todo - check for key restrictions?
|
||||||
if d is not None:
|
if d is not None:
|
||||||
if available_doors is not None:
|
if available_doors is not None:
|
||||||
available_doors.remove(d)
|
available_doors.remove(d)
|
||||||
d.parentChunk = chunk
|
d.parentChunk = chunk
|
||||||
if not d.connected:
|
if d.dest is None:
|
||||||
chunk.outflow += 1
|
chunk.outflow += 1
|
||||||
# direction of door catalog ?
|
# direction of door catalog ?
|
||||||
chunk.unlinked_doors.add(d)
|
chunk.unlinked_doors.add(d)
|
||||||
@@ -438,11 +522,11 @@ def valid_self_pick(src_door, dest_door):
|
|||||||
return False
|
return False
|
||||||
|
|
||||||
|
|
||||||
def is_dungeon_finished(world, dungeon):
|
def is_dungeon_finished(world, player, dungeon):
|
||||||
if len(dungeon.unlinked_doors) > 0: # no unlinked doors
|
if len(dungeon.unlinked_doors) > 0: # no unlinked doors
|
||||||
return False
|
return False
|
||||||
for path in dungeon.paths: # paths through dungeon are possible
|
for path in dungeon.paths: # paths through dungeon are possible
|
||||||
if not find_path(world, path, dungeon.path_completion):
|
if not find_path(world, player, path, dungeon.path_completion):
|
||||||
return False
|
return False
|
||||||
# if dungeon.chests < dungeon.count_dungeon_item() + 2: # 2 or more chests reachable in dungeon than number of dungeon items
|
# if dungeon.chests < dungeon.count_dungeon_item() + 2: # 2 or more chests reachable in dungeon than number of dungeon items
|
||||||
# return False
|
# return False
|
||||||
@@ -451,11 +535,11 @@ def is_dungeon_finished(world, dungeon):
|
|||||||
return True
|
return True
|
||||||
|
|
||||||
|
|
||||||
def find_path(world, path, path_completion):
|
def find_path(world, player, path, path_completion):
|
||||||
if path_completion[path]: # found it earlier -- assuming no disconnects
|
if path_completion[path]: # found it earlier -- assuming no disconnects
|
||||||
return True
|
return True
|
||||||
visited_regions = set([])
|
visited_regions = set([])
|
||||||
queue = collections.deque([world.get_region(path[0])])
|
queue = collections.deque([world.get_region(path[0], player)])
|
||||||
while len(queue) > 0:
|
while len(queue) > 0:
|
||||||
region = queue.popleft()
|
region = queue.popleft()
|
||||||
if region.name == path[1]:
|
if region.name == path[1]:
|
||||||
@@ -469,68 +553,18 @@ def find_path(world, path, path_completion):
|
|||||||
queue.append(connected)
|
queue.append(connected)
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
def experiment(world, player):
|
||||||
def switch_dir(direction):
|
for ent, ext in experimental_connections:
|
||||||
oppositemap = {
|
if world.get_door(ent, player).blocked:
|
||||||
Direction.South: Direction.North,
|
connect_one_way(world, ext, ent, player)
|
||||||
Direction.North: Direction.South,
|
elif world.get_door(ext, player).blocked:
|
||||||
Direction.West: Direction.East,
|
connect_one_way(world, ent, ext, player)
|
||||||
Direction.East: Direction.West,
|
else:
|
||||||
}
|
connect_two_way(world, ent, ext, player)
|
||||||
return oppositemap[direction]
|
|
||||||
|
|
||||||
|
|
||||||
def connect_simple_door(world, exit_name, region_name, player):
|
|
||||||
world.get_entrance(exit_name, player).connect(world.get_region(region_name, player))
|
|
||||||
d = world.check_for_door(exit_name, player)
|
|
||||||
if d is not None:
|
|
||||||
d.connected = True
|
|
||||||
|
|
||||||
|
|
||||||
def connect_two_way(world, entrancename, exitname, player):
|
|
||||||
entrance = world.get_entrance(entrancename, player)
|
|
||||||
ext = world.get_entrance(exitname, player)
|
|
||||||
|
|
||||||
# if these were already connected somewhere, remove the backreference
|
|
||||||
if entrance.connected_region is not None:
|
|
||||||
entrance.connected_region.entrances.remove(entrance, player)
|
|
||||||
if ext.connected_region is not None:
|
|
||||||
ext.connected_region.entrances.remove(ext)
|
|
||||||
|
|
||||||
# todo - rom indications, access rules for the doors...
|
|
||||||
entrance.connect(ext.parent_region)
|
|
||||||
ext.connect(entrance.parent_region)
|
|
||||||
if entrance.parent_region.dungeon:
|
|
||||||
ext.parent_region.dungeon = entrance.parent_region.dungeon
|
|
||||||
d = world.check_for_door(entrancename, player)
|
|
||||||
if d is not None:
|
|
||||||
d.connected = True
|
|
||||||
d = world.check_for_door(exitname, player)
|
|
||||||
if d is not None:
|
|
||||||
d.connected = True
|
|
||||||
# world.spoiler.set_entrance(entrance.name, exit.name, 'both') # todo: spoiler stuff
|
|
||||||
|
|
||||||
def connect_one_way(world, entrancename, exitname, player):
|
|
||||||
entrance = world.get_entrance(entrancename, player)
|
|
||||||
ext = world.get_entrance(exitname, player)
|
|
||||||
|
|
||||||
# if these were already connected somewhere, remove the backreference
|
|
||||||
if entrance.connected_region is not None:
|
|
||||||
entrance.connected_region.entrances.remove(entrance, player)
|
|
||||||
if ext.connected_region is not None:
|
|
||||||
ext.connected_region.entrances.remove(ext)
|
|
||||||
|
|
||||||
entrance.connect(ext.parent_region)
|
|
||||||
d = world.check_for_door(entrancename, player)
|
|
||||||
if entrance.parent_region.dungeon:
|
|
||||||
ext.parent_region.dungeon = entrance.parent_region.dungeon
|
|
||||||
if d is not None:
|
|
||||||
d.connected = True
|
|
||||||
d = world.check_for_door(exitname, player)
|
|
||||||
if d is not None:
|
|
||||||
d.connected = True
|
|
||||||
# spoiler info goes here?
|
|
||||||
|
|
||||||
|
# DATA GOES DOWN HERE
|
||||||
|
|
||||||
mandatory_connections = [('Hyrule Dungeon North Abyss Catwalk Dropdown', 'Hyrule Dungeon North Abyss'),
|
mandatory_connections = [('Hyrule Dungeon North Abyss Catwalk Dropdown', 'Hyrule Dungeon North Abyss'),
|
||||||
('Hyrule Dungeon Key Door S', 'Hyrule Dungeon North Abyss'),
|
('Hyrule Dungeon Key Door S', 'Hyrule Dungeon North Abyss'),
|
||||||
@@ -580,7 +614,7 @@ default_door_connections = [('Hyrule Castle Lobby W', 'Hyrule Castle West Lobby
|
|||||||
('Hyrule Castle Lobby WN', 'Hyrule Castle West Lobby EN'),
|
('Hyrule Castle Lobby WN', 'Hyrule Castle West Lobby EN'),
|
||||||
('Hyrule Castle West Lobby N', 'Hyrule Castle West Hall S'),
|
('Hyrule Castle West Lobby N', 'Hyrule Castle West Hall S'),
|
||||||
('Hyrule Castle East Lobby N', 'Hyrule Castle East Hall S'),
|
('Hyrule Castle East Lobby N', 'Hyrule Castle East Hall S'),
|
||||||
('Hyrule Castle East Lobby NE', 'Hyrule Castle East Hall SE'),
|
('Hyrule Castle East Lobby NW', 'Hyrule Castle East Hall SW'),
|
||||||
('Hyrule Castle East Hall W', 'Hyrule Castle Back Hall E'),
|
('Hyrule Castle East Hall W', 'Hyrule Castle Back Hall E'),
|
||||||
('Hyrule Castle West Hall E', 'Hyrule Castle Back Hall W'),
|
('Hyrule Castle West Hall E', 'Hyrule Castle Back Hall W'),
|
||||||
('Hyrule Castle Throne Room N', 'Sewers Behind Tapestry S'),
|
('Hyrule Castle Throne Room N', 'Sewers Behind Tapestry S'),
|
||||||
@@ -604,3 +638,24 @@ default_door_connections = [('Hyrule Castle Lobby W', 'Hyrule Castle West Lobby
|
|||||||
# ('', ''),
|
# ('', ''),
|
||||||
default_one_way_connections = [('Sewers Pull Switch S', 'Sanctuary N'),
|
default_one_way_connections = [('Sewers Pull Switch S', 'Sanctuary N'),
|
||||||
('Eastern Big Key NE', 'Eastern Compass Area SW')]
|
('Eastern Big Key NE', 'Eastern Compass Area SW')]
|
||||||
|
|
||||||
|
|
||||||
|
experimental_connections = [('Eastern Boss SE', 'Eastern Courtyard N'),
|
||||||
|
('Eastern Courtyard EN', 'Eastern Attic Switches WS'),
|
||||||
|
('Eastern Lobby N', 'Eastern Darkness S'),
|
||||||
|
('Eastern Courtyard WN', 'Eastern Compass Area E'),
|
||||||
|
('Eastern Attic Switches ES', 'Eastern Cannonball Ledge WN'),
|
||||||
|
('Eastern Compass Area EN', 'Hyrule Castle Back Hall W'),
|
||||||
|
('Hyrule Castle Back Hall E', 'Eastern Map Area W'),
|
||||||
|
('Eastern Attic Start WS', 'Eastern Cannonball Ledge Key Door EN'),
|
||||||
|
('Eastern Compass Area SW', 'Hyrule Dungeon Guardroom N'),
|
||||||
|
('Hyrule Castle East Lobby NW', 'Hyrule Castle East Hall SW'),
|
||||||
|
('Hyrule Castle East Lobby N', 'Eastern Courtyard Ledge S'),
|
||||||
|
('Hyrule Castle Lobby E', 'Eastern Courtyard Ledge W'),
|
||||||
|
('Hyrule Castle Lobby WN', 'Eastern Courtyard Ledge E'),
|
||||||
|
('Hyrule Castle West Lobby EN', 'Hyrule Castle East Lobby W'),
|
||||||
|
('Hyrule Castle Throne Room N', 'Hyrule Castle East Hall S'),
|
||||||
|
('Hyrule Castle West Lobby E', 'Hyrule Castle East Hall W'),
|
||||||
|
('Hyrule Castle West Lobby N', 'Hyrule Dungeon Armory S'),
|
||||||
|
('Hyrule Castle Lobby W', 'Hyrule Castle West Hall E'),
|
||||||
|
('Hyrule Castle West Hall S', 'Sanctuary N')]
|
||||||
|
|||||||
202
Doors.py
202
Doors.py
@@ -1,99 +1,133 @@
|
|||||||
|
|
||||||
from BaseClasses import Door, DoorType, Direction
|
from BaseClasses import Door, DoorType, Direction
|
||||||
|
|
||||||
|
# constants
|
||||||
|
Top = 0
|
||||||
|
Left = 0
|
||||||
|
Mid = 1
|
||||||
|
Bot = 2
|
||||||
|
Right = 2
|
||||||
|
|
||||||
|
|
||||||
def create_doors(world, player):
|
def create_doors(world, player):
|
||||||
world.doors += [
|
world.doors += [
|
||||||
# hyrule castle
|
# hyrule castle
|
||||||
create_door(player, 'Hyrule Castle Lobby W', DoorType.Normal, Direction.West),
|
create_toggle_door(player, 'Hyrule Castle Lobby W', DoorType.Normal, Direction.West, 0x61, Mid, 0),
|
||||||
create_door(player, 'Hyrule Castle Lobby E', DoorType.Normal, Direction.East),
|
create_toggle_door(player, 'Hyrule Castle Lobby E', DoorType.Normal, Direction.East, 0x61, Mid, 0),
|
||||||
create_door(player, 'Hyrule Castle Lobby WN', DoorType.Normal, Direction.West),
|
create_dir_door(player, 'Hyrule Castle Lobby WN', DoorType.Normal, Direction.West, 0x61, Top, 0),
|
||||||
create_door(player, 'Hyrule Castle Lobby North Stairs', DoorType.StraightStairs, Direction.North),
|
create_dir_door(player, 'Hyrule Castle Lobby North Stairs', DoorType.StraightStairs, Direction.North, 0x61, Mid, 0),
|
||||||
create_door(player, 'Hyrule Castle West Lobby E', DoorType.Normal, Direction.East),
|
create_toggle_door(player, 'Hyrule Castle West Lobby E', DoorType.Normal, Direction.East, 0x60, Mid, 1),
|
||||||
create_door(player, 'Hyrule Castle West Lobby N', DoorType.Normal, Direction.North),
|
create_dir_door(player, 'Hyrule Castle West Lobby N', DoorType.Normal, Direction.North, 0x60, Right, 1),
|
||||||
create_door(player, 'Hyrule Castle West Lobby EN', DoorType.Normal, Direction.East),
|
create_dir_door(player, 'Hyrule Castle West Lobby EN', DoorType.Normal, Direction.East, 0x60, Top, 1),
|
||||||
create_door(player, 'Hyrule Castle East Lobby W', DoorType.Normal, Direction.West),
|
create_toggle_door(player, 'Hyrule Castle East Lobby W', DoorType.Normal, Direction.West, 0x62, Mid, 1),
|
||||||
create_door(player, 'Hyrule Castle East Lobby N', DoorType.Normal, Direction.North),
|
create_dir_door(player, 'Hyrule Castle East Lobby N', DoorType.Normal, Direction.North, 0x62, Mid, 0),
|
||||||
create_door(player, 'Hyrule Castle East Lobby NE', DoorType.Normal, Direction.North),
|
create_dir_door(player, 'Hyrule Castle East Lobby NW', DoorType.Normal, Direction.North, 0x62, Left, 1),
|
||||||
create_door(player, 'Hyrule Castle East Hall W', DoorType.Normal, Direction.West),
|
create_dir_door(player, 'Hyrule Castle East Hall W', DoorType.Normal, Direction.West, 0x52, Top, 1),
|
||||||
create_door(player, 'Hyrule Castle East Hall S', DoorType.Normal, Direction.South),
|
create_dir_door(player, 'Hyrule Castle East Hall S', DoorType.Normal, Direction.South, 0x52, Mid, 0),
|
||||||
create_door(player, 'Hyrule Castle East Hall SE', DoorType.Normal, Direction.South),
|
create_dir_door(player, 'Hyrule Castle East Hall SW', DoorType.Normal, Direction.South, 0x52, Left, 1),
|
||||||
create_door(player, 'Hyrule Castle West Hall E', DoorType.Normal, Direction.East),
|
create_dir_door(player, 'Hyrule Castle West Hall E', DoorType.Normal, Direction.East, 0x50, Top, 1),
|
||||||
create_door(player, 'Hyrule Castle West Hall S', DoorType.Normal, Direction.South),
|
create_dir_door(player, 'Hyrule Castle West Hall S', DoorType.Normal, Direction.South, 0x50, Right, 1),
|
||||||
create_door(player, 'Hyrule Castle Back Hall W', DoorType.Normal, Direction.West),
|
create_dir_door(player, 'Hyrule Castle Back Hall W', DoorType.Normal, Direction.West, 0x01, Top, 1),
|
||||||
create_door(player, 'Hyrule Castle Back Hall E', DoorType.Normal, Direction.East),
|
create_dir_door(player, 'Hyrule Castle Back Hall E', DoorType.Normal, Direction.East, 0x01, Top, 1),
|
||||||
create_door(player, 'Hyrule Castle Back Hall Down Stairs', DoorType.SpiralStairs, None),
|
create_door(player, 'Hyrule Castle Back Hall Down Stairs', DoorType.SpiralStairs),
|
||||||
create_door(player, 'Hyrule Castle Throne Room N', DoorType.Normal, Direction.North),
|
create_dir_door(player, 'Hyrule Castle Throne Room N', DoorType.Normal, Direction.North, 0x51, Mid, 0),
|
||||||
create_door(player, 'Hyrule Castle Throne Room South Stairs', DoorType.StraightStairs, Direction.South),
|
create_dir_door(player, 'Hyrule Castle Throne Room South Stairs', DoorType.StraightStairs, Direction.South, 0x51, Mid, 1),
|
||||||
|
|
||||||
# hyrule dungeon level
|
# hyrule dungeon level
|
||||||
create_door(player, 'Hyrule Dungeon Map Room Up Stairs', DoorType.SpiralStairs, None),
|
create_door(player, 'Hyrule Dungeon Map Room Up Stairs', DoorType.SpiralStairs),
|
||||||
create_door(player, 'Hyrule Dungeon North Abyss South Edge', DoorType.Open, Direction.South),
|
create_dir_door(player, 'Hyrule Dungeon North Abyss South Edge', DoorType.Open, Direction.South, 0x72, None, 1),
|
||||||
create_door(player, 'Hyrule Dungeon North Abyss Catwalk Edge', DoorType.Open, Direction.South),
|
create_dir_door(player, 'Hyrule Dungeon North Abyss Catwalk Edge', DoorType.Open, Direction.South, 0x72, None, 0),
|
||||||
create_door(player, 'Hyrule Dungeon South Abyss North Edge', DoorType.Open, Direction.North),
|
create_dir_door(player, 'Hyrule Dungeon South Abyss North Edge', DoorType.Open, Direction.North, 0x82, None, 1),
|
||||||
create_door(player, 'Hyrule Dungeon South Abyss West Edge', DoorType.Open, Direction.West),
|
create_dir_door(player, 'Hyrule Dungeon South Abyss West Edge', DoorType.Open, Direction.West, 0x82, None, 1),
|
||||||
create_door(player, 'Hyrule Dungeon South Abyss Catwalk North Edge', DoorType.Open, Direction.North),
|
create_dir_door(player, 'Hyrule Dungeon South Abyss Catwalk North Edge', DoorType.Open, Direction.North, 0x82, None, 0),
|
||||||
create_door(player, 'Hyrule Dungeon South Abyss Catwalk West Edge', DoorType.Open, Direction.West),
|
create_dir_door(player, 'Hyrule Dungeon South Abyss Catwalk West Edge', DoorType.Open, Direction.West, 0x82, None, 0),
|
||||||
create_door(player, 'Hyrule Dungeon Guardroom Catwalk Edge', DoorType.Open, Direction.East),
|
create_dir_door(player, 'Hyrule Dungeon Guardroom Catwalk Edge', DoorType.Open, Direction.East, 0x81, None, 0),
|
||||||
create_door(player, 'Hyrule Dungeon Guardroom Abyss Edge', DoorType.Open, Direction.West),
|
create_dir_door(player, 'Hyrule Dungeon Guardroom Abyss Edge', DoorType.Open, Direction.West, 0x81, None, 0),
|
||||||
create_door(player, 'Hyrule Dungeon Guardroom N', DoorType.Normal, Direction.North),
|
create_dir_door(player, 'Hyrule Dungeon Guardroom N', DoorType.Normal, Direction.North, 0x71, Left, 1),
|
||||||
create_door(player, 'Hyrule Dungeon Armory S', DoorType.Normal, Direction.South),
|
create_dir_door(player, 'Hyrule Dungeon Armory S', DoorType.Normal, Direction.South, 0x71, Left, 1),
|
||||||
create_door(player, 'Hyrule Dungeon Armory Down Stairs', DoorType.SpiralStairs, None),
|
create_door(player, 'Hyrule Dungeon Armory Down Stairs', DoorType.SpiralStairs),
|
||||||
create_door(player, 'Hyrule Dungeon Staircase Up Stairs', DoorType.SpiralStairs, None),
|
create_door(player, 'Hyrule Dungeon Staircase Up Stairs', DoorType.SpiralStairs),
|
||||||
create_door(player, 'Hyrule Dungeon Staircase Down Stair', DoorType.SpiralStairs, None),
|
create_door(player, 'Hyrule Dungeon Staircase Down Stairs', DoorType.SpiralStairs),
|
||||||
create_door(player, 'Hyrule Dungeon Cellblock Up Stairs', DoorType.SpiralStairs, None),
|
create_door(player, 'Hyrule Dungeon Cellblock Up Stairs', DoorType.SpiralStairs),
|
||||||
|
|
||||||
# sewers
|
# sewers
|
||||||
create_door(player, 'Sewers Behind Tapestry S', DoorType.Normal, Direction.South), # one-way, this door is locked
|
create_blocked_door(player, 'Sewers Behind Tapestry S', DoorType.Normal, Direction.South, 0x41, Mid, 0),
|
||||||
create_door(player, 'Sewers Behind Tapestry Down Stairs', DoorType.SpiralStairs, None),
|
create_door(player, 'Sewers Behind Tapestry Down Stairs', DoorType.SpiralStairs),
|
||||||
create_door(player, 'Sewers Rope Room Up Stairs', DoorType.SpiralStairs, None),
|
create_door(player, 'Sewers Rope Room Up Stairs', DoorType.SpiralStairs),
|
||||||
create_door(player, 'Sewers Rope Room North Stairs', DoorType.StraightStairs, Direction.North),
|
create_dir_door(player, 'Sewers Rope Room North Stairs', DoorType.StraightStairs, Direction.North, 0x42, Mid, 0),
|
||||||
create_door(player, 'Sewers Dark Cross South Stairs', DoorType.StraightStairs, Direction.South),
|
create_dir_door(player, 'Sewers Dark Cross South Stairs', DoorType.StraightStairs, Direction.South, 0x32, Mid, 0),
|
||||||
create_door(player, 'Sewers Dark Cross Key Door N', DoorType.Normal, Direction.North),
|
create_dir_door(player, 'Sewers Dark Cross Key Door N', DoorType.Normal, Direction.North, 0x32, Mid, 0),
|
||||||
create_door(player, 'Sewers Dark Cross Key Door S', DoorType.Normal, Direction.South),
|
create_dir_door(player, 'Sewers Dark Cross Key Door S', DoorType.Normal, Direction.South, 0x22, Mid, 0),
|
||||||
create_door(player, 'Sewers Water W', DoorType.Normal, Direction.West),
|
create_dir_door(player, 'Sewers Water W', DoorType.Normal, Direction.West, 0x22, Bot, 0),
|
||||||
create_door(player, 'Sewers Key Rat E', DoorType.Normal, Direction.East),
|
create_dir_door(player, 'Sewers Key Rat E', DoorType.Normal, Direction.East, 0x21, Bot, 0),
|
||||||
create_door(player, 'Sewers Key Rat Key Door N', DoorType.Normal, Direction.North),
|
create_small_key_door(player, 'Sewers Key Rat Key Door N', DoorType.Normal, Direction.North, 0x21, Right, 0),
|
||||||
create_door(player, 'Sewers Secret Room Key Door S', DoorType.Normal, Direction.South),
|
create_small_key_door(player, 'Sewers Secret Room Key Door S', DoorType.Normal, Direction.South, 0x11, Right, 0),
|
||||||
create_door(player, 'Sewers Secret Room Up Stairs', DoorType.SpiralStairs, None),
|
create_door(player, 'Sewers Secret Room Up Stairs', DoorType.SpiralStairs),
|
||||||
create_door(player, 'Sewers Pull Switch Down Stairs', DoorType.SpiralStairs, None),
|
create_door(player, 'Sewers Pull Switch Down Stairs', DoorType.SpiralStairs),
|
||||||
create_door(player, 'Sewers Pull Switch S', DoorType.Normal, Direction.South),
|
create_dir_door(player, 'Sewers Pull Switch S', DoorType.Normal, Direction.South, 0x02, Mid, 0),
|
||||||
create_door(player, 'Sanctuary N', DoorType.Normal, Direction.North), # logically one way, but should be linked
|
create_blocked_door(player, 'Sanctuary N', DoorType.Normal, Direction.North, 0x12, Mid, 0), # logically one way, but should be linked
|
||||||
|
|
||||||
# Eastern Palace
|
# Eastern Palace
|
||||||
create_door(player, 'Eastern Lobby N', DoorType.Normal, Direction.North),
|
create_dir_door(player, 'Eastern Lobby N', DoorType.Normal, Direction.North, 0xc9, Mid, 0),
|
||||||
create_door(player, 'Eastern Cannonball S', DoorType.Normal, Direction.South),
|
create_dir_door(player, 'Eastern Cannonball S', DoorType.Normal, Direction.South, 0xb9, Mid, 0),
|
||||||
create_door(player, 'Eastern Cannonball N', DoorType.Normal, Direction.North),
|
create_dir_door(player, 'Eastern Cannonball N', DoorType.Normal, Direction.North, 0xb9, Mid, 0),
|
||||||
create_door(player, 'Eastern Cannonball Ledge WN', DoorType.Normal, Direction.West),
|
create_dir_door(player, 'Eastern Cannonball Ledge WN', DoorType.Normal, Direction.West, 0xb9, Top, 0),
|
||||||
create_door(player, 'Eastern Cannonball Ledge Key Door EN', DoorType.Normal, Direction.East),
|
create_small_key_door(player, 'Eastern Cannonball Ledge Key Door EN', DoorType.Normal, Direction.East, 0xb9, Top, 0),
|
||||||
create_door(player, 'Eastern Courtyard Ledge S', DoorType.Normal, Direction.South),
|
create_dir_door(player, 'Eastern Courtyard Ledge S', DoorType.Normal, Direction.South, 0xa9, Mid, 0),
|
||||||
create_door(player, 'Eastern Courtyard Ledge W', DoorType.Normal, Direction.West),
|
create_dir_door(player, 'Eastern Courtyard Ledge W', DoorType.Normal, Direction.West, 0xa9, Mid, 0),
|
||||||
create_door(player, 'Eastern Courtyard Ledge E', DoorType.Normal, Direction.East),
|
create_dir_door(player, 'Eastern Courtyard Ledge E', DoorType.Normal, Direction.East, 0xa9, Mid, 0),
|
||||||
create_door(player, 'Eastern Map Area W', DoorType.Normal, Direction.West),
|
create_dir_door(player, 'Eastern Map Area W', DoorType.Normal, Direction.West, 0xaa, Mid, 0),
|
||||||
create_door(player, 'Eastern Compass Area E', DoorType.Normal, Direction.East),
|
create_dir_door(player, 'Eastern Compass Area E', DoorType.Normal, Direction.East, 0xa8, Mid, 0),
|
||||||
create_door(player, 'Eastern Compass Area EN', DoorType.Normal, Direction.East),
|
create_dir_door(player, 'Eastern Compass Area EN', DoorType.Normal, Direction.East, 0xa8, Top, 0),
|
||||||
create_door(player, 'Eastern Compass Area SW', DoorType.Normal, Direction.South), # one-way
|
create_blocked_door(player, 'Eastern Compass Area SW', DoorType.Normal, Direction.South, 0xa8, Right, 0),
|
||||||
create_door(player, 'Eastern Courtyard WN', DoorType.Normal, Direction.West),
|
create_dir_door(player, 'Eastern Courtyard WN', DoorType.Normal, Direction.West, 0xa9, Top, 1),
|
||||||
create_door(player, 'Eastern Courtyard EN', DoorType.Normal, Direction.East),
|
create_dir_door(player, 'Eastern Courtyard EN', DoorType.Normal, Direction.East, 0xa9, Top, 1),
|
||||||
create_door(player, 'Eastern Courtyard N', DoorType.Normal, Direction.North), # big key
|
create_big_key_door(player, 'Eastern Courtyard N', DoorType.Normal, Direction.North, 0xa9, Mid, 0),
|
||||||
create_door(player, 'Eastern Courtyard Potholes', DoorType.Hole, None),
|
create_door(player, 'Eastern Courtyard Potholes', DoorType.Hole),
|
||||||
create_door(player, 'Eastern Fairies\' Warp', DoorType.Warp, None),
|
create_door(player, 'Eastern Fairies\' Warp', DoorType.Warp),
|
||||||
create_door(player, 'Eastern Map Valley WN', DoorType.Normal, Direction.West),
|
create_dir_door(player, 'Eastern Map Valley WN', DoorType.Normal, Direction.West, 0xaa, Top, 1),
|
||||||
create_door(player, 'Eastern Map Valley SW', DoorType.Normal, Direction.South),
|
create_dir_door(player, 'Eastern Map Valley SW', DoorType.Normal, Direction.South, 0xaa, Left, 0),
|
||||||
create_door(player, 'Eastern Dark Square NW', DoorType.Normal, Direction.North),
|
create_small_key_door(player, 'Eastern Dark Square NW', DoorType.Normal, Direction.North, 0xba, Left, 0),
|
||||||
create_door(player, 'Eastern Dark Square Key Door WN', DoorType.Normal, Direction.West),
|
create_small_key_door(player, 'Eastern Dark Square Key Door WN', DoorType.Normal, Direction.West, 0xba, Top, 0),
|
||||||
create_door(player, 'Eastern Big Key EN', DoorType.Normal, Direction.East),
|
create_small_key_door(player, 'Eastern Big Key EN', DoorType.Normal, Direction.East, 0xb8, Top, 0),
|
||||||
create_door(player, 'Eastern Big Key NE', DoorType.Normal, Direction.North),
|
create_dir_door(player, 'Eastern Big Key NE', DoorType.Normal, Direction.North, 0xb8, Right, 0),
|
||||||
create_door(player, 'Eastern Darkness S', DoorType.Normal, Direction.South), # small key?
|
create_small_key_door(player, 'Eastern Darkness S', DoorType.Normal, Direction.South, 0x99, Mid, 0),
|
||||||
create_door(player, 'Eastern Darkness Up Stairs', DoorType.SpiralStairs, None),
|
create_door(player, 'Eastern Darkness Up Stairs', DoorType.SpiralStairs),
|
||||||
create_door(player, 'Eastern Attic Start Down Stairs', DoorType.SpiralStairs, None),
|
create_door(player, 'Eastern Attic Start Down Stairs', DoorType.SpiralStairs),
|
||||||
create_door(player, 'Eastern Attic Start WS', DoorType.Normal, Direction.West),
|
create_dir_door(player, 'Eastern Attic Start WS', DoorType.Normal, Direction.West, 0xda, Bot, 0),
|
||||||
create_door(player, 'Eastern Attic Switches ES', DoorType.Normal, Direction.East),
|
create_dir_door(player, 'Eastern Attic Switches ES', DoorType.Normal, Direction.East, 0xd9, Bot, 0),
|
||||||
create_door(player, 'Eastern Attic Switches WS', DoorType.Normal, Direction.West),
|
create_dir_door(player, 'Eastern Attic Switches WS', DoorType.Normal, Direction.West, 0xd9, Bot, 0),
|
||||||
create_door(player, 'Eastern Eyegores ES', DoorType.Normal, Direction.East),
|
create_dir_door(player, 'Eastern Eyegores ES', DoorType.Normal, Direction.East, 0xd8, Bot, 0),
|
||||||
create_door(player, 'Eastern Eyegores NE', DoorType.Normal, Direction.North),
|
create_dir_door(player, 'Eastern Eyegores NE', DoorType.Normal, Direction.North, 0xd8, Right, 0),
|
||||||
create_door(player, 'Eastern Boss SE', DoorType.Normal, Direction.South),
|
create_dir_door(player, 'Eastern Boss SE', DoorType.Normal, Direction.South, 0xd8, Right, 0),
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
def create_door(player, name, type, direction):
|
def create_door(player, name, type):
|
||||||
return Door(player, name, type, direction)
|
return Door(player, name, type, None, None, None, None)
|
||||||
|
|
||||||
|
|
||||||
|
def create_small_key_door(player, name, type, direction, room, doorIndex, layer):
|
||||||
|
d = Door(player, name, type, direction, room, doorIndex, layer)
|
||||||
|
d.smallKey = True
|
||||||
|
return d
|
||||||
|
|
||||||
|
|
||||||
|
def create_big_key_door(player, name, type, direction, room, doorIndex, layer):
|
||||||
|
d = Door(player, name, type, direction, room, doorIndex, layer)
|
||||||
|
d.bigKey = True
|
||||||
|
return d
|
||||||
|
|
||||||
|
|
||||||
|
def create_blocked_door(player, name, type, direction, room, doorIndex, layer):
|
||||||
|
d = Door(player, name, type, direction, room, doorIndex, layer)
|
||||||
|
d.blocked = True
|
||||||
|
return d
|
||||||
|
|
||||||
|
|
||||||
|
def create_dir_door(player, name, type, direction, room, doorIndex, layer):
|
||||||
|
return Door(player, name, type, direction, room, doorIndex, layer)
|
||||||
|
|
||||||
|
|
||||||
|
def create_toggle_door(player, name, type, direction, room, doorIndex, layer):
|
||||||
|
return Door(player, name, type, direction, room, doorIndex, layer, True)
|
||||||
|
|||||||
@@ -118,7 +118,7 @@ def start():
|
|||||||
parser.add_argument('--algorithm', default='balanced', const='balanced', nargs='?', choices=['freshness', 'flood', 'vt21', 'vt22', 'vt25', 'vt26', 'balanced'],
|
parser.add_argument('--algorithm', default='balanced', const='balanced', nargs='?', choices=['freshness', 'flood', 'vt21', 'vt22', 'vt25', 'vt26', 'balanced'],
|
||||||
help='''\
|
help='''\
|
||||||
Select item filling algorithm. (default: %(default)s
|
Select item filling algorithm. (default: %(default)s
|
||||||
balanced: vt26 derivitive that aims to strike a balance between
|
balanced: vt26 derivative that aims to strike a balance between
|
||||||
the overworld heavy vt25 and the dungeon heavy vt26
|
the overworld heavy vt25 and the dungeon heavy vt26
|
||||||
algorithm.
|
algorithm.
|
||||||
vt26: Shuffle items and place them in a random location
|
vt26: Shuffle items and place them in a random location
|
||||||
@@ -162,6 +162,17 @@ def start():
|
|||||||
The dungeon variants only mix up dungeons and keep the rest of
|
The dungeon variants only mix up dungeons and keep the rest of
|
||||||
the overworld vanilla.
|
the overworld vanilla.
|
||||||
''')
|
''')
|
||||||
|
parser.add_argument('--door_shuffle', default='vanilla', const='vanilla', nargs='?', choices=['vanilla', 'basic', 'crossed', 'experimental'],
|
||||||
|
help='''\
|
||||||
|
Select Door Shuffling Algorithm. (default: %(default)s)
|
||||||
|
Basic: Doors are mixed within a single dungeon.
|
||||||
|
(Not yet implemented)
|
||||||
|
Crossed: Doors are mixed between all dungeons.
|
||||||
|
(Not yet implemented)
|
||||||
|
Vanilla: All doors are connected the same way the were in the
|
||||||
|
base game.
|
||||||
|
Experimental: Experimental mixes live here. Use at your own risk.
|
||||||
|
''')
|
||||||
parser.add_argument('--crystals_ganon', default='7', const='7', nargs='?', choices=['random', '0', '1', '2', '3', '4', '5', '6', '7'],
|
parser.add_argument('--crystals_ganon', default='7', const='7', nargs='?', choices=['random', '0', '1', '2', '3', '4', '5', '6', '7'],
|
||||||
help='''\
|
help='''\
|
||||||
How many crystals are needed to defeat ganon. Any other
|
How many crystals are needed to defeat ganon. Any other
|
||||||
|
|||||||
13
Gui.py
13
Gui.py
@@ -18,7 +18,7 @@ from Utils import is_bundled, local_path, output_path, open_file
|
|||||||
|
|
||||||
def guiMain(args=None):
|
def guiMain(args=None):
|
||||||
mainWindow = Tk()
|
mainWindow = Tk()
|
||||||
mainWindow.wm_title("Entrance Shuffle %s" % ESVersion)
|
mainWindow.wm_title("Door Shuffle %s" % ESVersion)
|
||||||
|
|
||||||
set_icon(mainWindow)
|
set_icon(mainWindow)
|
||||||
|
|
||||||
@@ -203,6 +203,14 @@ def guiMain(args=None):
|
|||||||
shuffleLabel = Label(shuffleFrame, text='Entrance shuffle algorithm')
|
shuffleLabel = Label(shuffleFrame, text='Entrance shuffle algorithm')
|
||||||
shuffleLabel.pack(side=LEFT)
|
shuffleLabel.pack(side=LEFT)
|
||||||
|
|
||||||
|
doorShuffleFrame = Frame(drowDownFrame)
|
||||||
|
doorShuffleVar = StringVar()
|
||||||
|
doorShuffleVar.set('vanilla')
|
||||||
|
doorShuffleOptionMenu = OptionMenu(doorShuffleFrame, doorShuffleVar, 'vanilla', 'basic', 'crosssed', 'experimental')
|
||||||
|
doorShuffleOptionMenu.pack(side=RIGHT)
|
||||||
|
doorShuffleLabel = Label(shuffleFrame, text='Door shuffle algorithm')
|
||||||
|
doorShuffleLabel.pack(side=LEFT)
|
||||||
|
|
||||||
heartbeepFrame = Frame(drowDownFrame)
|
heartbeepFrame = Frame(drowDownFrame)
|
||||||
heartbeepVar = StringVar()
|
heartbeepVar = StringVar()
|
||||||
heartbeepVar.set('normal')
|
heartbeepVar.set('normal')
|
||||||
@@ -235,6 +243,7 @@ def guiMain(args=None):
|
|||||||
progressiveFrame.pack(expand=True, anchor=E)
|
progressiveFrame.pack(expand=True, anchor=E)
|
||||||
algorithmFrame.pack(expand=True, anchor=E)
|
algorithmFrame.pack(expand=True, anchor=E)
|
||||||
shuffleFrame.pack(expand=True, anchor=E)
|
shuffleFrame.pack(expand=True, anchor=E)
|
||||||
|
doorShuffleFrame.pack(expand=True, anchor=E)
|
||||||
heartbeepFrame.pack(expand=True, anchor=E)
|
heartbeepFrame.pack(expand=True, anchor=E)
|
||||||
heartcolorFrame.pack(expand=True, anchor=E)
|
heartcolorFrame.pack(expand=True, anchor=E)
|
||||||
fastMenuFrame.pack(expand=True, anchor=E)
|
fastMenuFrame.pack(expand=True, anchor=E)
|
||||||
@@ -320,6 +329,7 @@ def guiMain(args=None):
|
|||||||
guiargs.progressive = progressiveVar.get()
|
guiargs.progressive = progressiveVar.get()
|
||||||
guiargs.algorithm = algorithmVar.get()
|
guiargs.algorithm = algorithmVar.get()
|
||||||
guiargs.shuffle = shuffleVar.get()
|
guiargs.shuffle = shuffleVar.get()
|
||||||
|
guiargs.door_shuffle = doorShuffleVar.get()
|
||||||
guiargs.heartbeep = heartbeepVar.get()
|
guiargs.heartbeep = heartbeepVar.get()
|
||||||
guiargs.heartcolor = heartcolorVar.get()
|
guiargs.heartcolor = heartcolorVar.get()
|
||||||
guiargs.fastmenu = fastMenuVar.get()
|
guiargs.fastmenu = fastMenuVar.get()
|
||||||
@@ -1080,6 +1090,7 @@ def guiMain(args=None):
|
|||||||
goalVar.set(args.goal)
|
goalVar.set(args.goal)
|
||||||
algorithmVar.set(args.algorithm)
|
algorithmVar.set(args.algorithm)
|
||||||
shuffleVar.set(args.shuffle)
|
shuffleVar.set(args.shuffle)
|
||||||
|
doorShuffleVar.set(args.door_shuffle)
|
||||||
heartbeepVar.set(args.heartbeep)
|
heartbeepVar.set(args.heartbeep)
|
||||||
fastMenuVar.set(args.fastmenu)
|
fastMenuVar.set(args.fastmenu)
|
||||||
logicVar.set(args.logic)
|
logicVar.set(args.logic)
|
||||||
|
|||||||
6
Main.py
6
Main.py
@@ -26,7 +26,7 @@ def main(args, seed=None):
|
|||||||
start = time.clock()
|
start = time.clock()
|
||||||
|
|
||||||
# initialize the world
|
# initialize the world
|
||||||
world = World(args.multi, args.shuffle, args.logic, args.mode, args.swords, args.difficulty, args.item_functionality, args.timer, args.progressive, args.goal, args.algorithm, not args.nodungeonitems, args.accessibility, args.shuffleganon, args.quickswap, args.fastmenu, args.disablemusic, args.keysanity, args.retro, args.custom, args.customitemarray, args.shufflebosses, args.hints)
|
world = World(args.multi, args.shuffle, args.door_shuffle, args.logic, args.mode, args.swords, args.difficulty, args.item_functionality, args.timer, args.progressive, args.goal, args.algorithm, not args.nodungeonitems, args.accessibility, args.shuffleganon, args.quickswap, args.fastmenu, args.disablemusic, args.keysanity, args.retro, args.custom, args.customitemarray, args.shufflebosses, args.hints)
|
||||||
logger = logging.getLogger('')
|
logger = logging.getLogger('')
|
||||||
if seed is None:
|
if seed is None:
|
||||||
random.seed(None)
|
random.seed(None)
|
||||||
@@ -129,7 +129,7 @@ def main(args, seed=None):
|
|||||||
else:
|
else:
|
||||||
sprite = None
|
sprite = None
|
||||||
|
|
||||||
outfilebase = 'ER_%s_%s-%s-%s-%s%s_%s-%s%s%s%s%s_%s' % (world.logic, world.difficulty, world.difficulty_adjustments, world.mode, world.goal, "" if world.timer in ['none', 'display'] else "-" + world.timer, world.shuffle, world.algorithm, "-keysanity" if world.keysanity else "", "-retro" if world.retro else "", "-prog_" + world.progressive if world.progressive in ['off', 'random'] else "", "-nohints" if not world.hints else "", world.seed)
|
outfilebase = 'DR_%s_%s-%s-%s-%s%s_%s-%s_%s%s%s%s%s_%s' % (world.logic, world.difficulty, world.difficulty_adjustments, world.mode, world.goal, "" if world.timer in ['none', 'display'] else "-" + world.timer, world.shuffle, world.algorithm, world.doorShuffle, "-keysanity" if world.keysanity else "", "-retro" if world.retro else "", "-prog_" + world.progressive if world.progressive in ['off', 'random'] else "", "-nohints" if not world.hints else "", world.seed)
|
||||||
|
|
||||||
use_enemizer = args.enemizercli and (args.shufflebosses != 'none' or args.shuffleenemies or args.enemy_health != 'default' or args.enemy_health != 'default' or args.enemy_damage or args.shufflepalette or args.shufflepots)
|
use_enemizer = args.enemizercli and (args.shufflebosses != 'none' or args.shuffleenemies or args.enemy_health != 'default' or args.enemy_health != 'default' or args.enemy_damage or args.shufflepalette or args.shufflepots)
|
||||||
|
|
||||||
@@ -192,7 +192,7 @@ def gt_filler(world):
|
|||||||
|
|
||||||
def copy_world(world):
|
def copy_world(world):
|
||||||
# ToDo: Not good yet
|
# ToDo: Not good yet
|
||||||
ret = World(world.players, world.shuffle, world.logic, world.mode, world.swords, world.difficulty, world.difficulty_adjustments, world.timer, world.progressive, world.goal, world.algorithm, world.place_dungeon_items, world.accessibility, world.shuffle_ganon, world.quickswap, world.fastmenu, world.disable_music, world.keysanity, world.retro, world.custom, world.customitemarray, world.boss_shuffle, world.hints)
|
ret = World(world.players, world.shuffle, world.doorShuffle, world.logic, world.mode, world.swords, world.difficulty, world.difficulty_adjustments, world.timer, world.progressive, world.goal, world.algorithm, world.place_dungeon_items, world.accessibility, world.shuffle_ganon, world.quickswap, world.fastmenu, world.disable_music, world.keysanity, world.retro, world.custom, world.customitemarray, world.boss_shuffle, world.hints)
|
||||||
ret.required_medallions = world.required_medallions.copy()
|
ret.required_medallions = world.required_medallions.copy()
|
||||||
ret.swamp_patch_required = world.swamp_patch_required.copy()
|
ret.swamp_patch_required = world.swamp_patch_required.copy()
|
||||||
ret.ganon_at_pyramid = world.ganon_at_pyramid.copy()
|
ret.ganon_at_pyramid = world.ganon_at_pyramid.copy()
|
||||||
|
|||||||
@@ -289,9 +289,9 @@ def create_regions(world, player):
|
|||||||
create_dungeon_region(player, 'Hyrule Castle West Lobby', 'A dungeon', None, ['Hyrule Castle West Lobby E', 'Hyrule Castle West Lobby N',
|
create_dungeon_region(player, 'Hyrule Castle West Lobby', 'A dungeon', None, ['Hyrule Castle West Lobby E', 'Hyrule Castle West Lobby N',
|
||||||
'Hyrule Castle West Lobby EN', 'Hyrule Castle Exit (West)']),
|
'Hyrule Castle West Lobby EN', 'Hyrule Castle Exit (West)']),
|
||||||
create_dungeon_region(player, 'Hyrule Castle East Lobby', 'A dungeon', None, ['Hyrule Castle East Lobby W', 'Hyrule Castle East Lobby N',
|
create_dungeon_region(player, 'Hyrule Castle East Lobby', 'A dungeon', None, ['Hyrule Castle East Lobby W', 'Hyrule Castle East Lobby N',
|
||||||
'Hyrule Castle East Lobby NE', 'Hyrule Castle Exit (East)']),
|
'Hyrule Castle East Lobby NW', 'Hyrule Castle Exit (East)']),
|
||||||
create_dungeon_region(player, 'Hyrule Castle East Hall', 'A dungeon', None, ['Hyrule Castle East Hall W', 'Hyrule Castle East Hall S',
|
create_dungeon_region(player, 'Hyrule Castle East Hall', 'A dungeon', None, ['Hyrule Castle East Hall W', 'Hyrule Castle East Hall S',
|
||||||
'Hyrule Castle East Hall SE']),
|
'Hyrule Castle East Hall SW']),
|
||||||
create_dungeon_region(player, 'Hyrule Castle West Hall', 'A dungeon', None, ['Hyrule Castle West Hall E', 'Hyrule Castle West Hall S']),
|
create_dungeon_region(player, 'Hyrule Castle West Hall', 'A dungeon', None, ['Hyrule Castle West Hall E', 'Hyrule Castle West Hall S']),
|
||||||
create_dungeon_region(player, 'Hyrule Castle Back Hall', 'A dungeon', None, ['Hyrule Castle Back Hall E', 'Hyrule Castle Back Hall W', 'Hyrule Castle Back Hall Down Stairs']),
|
create_dungeon_region(player, 'Hyrule Castle Back Hall', 'A dungeon', None, ['Hyrule Castle Back Hall E', 'Hyrule Castle Back Hall W', 'Hyrule Castle Back Hall Down Stairs']),
|
||||||
create_dungeon_region(player, 'Hyrule Castle Throne Room', 'A dungeon', None, ['Hyrule Castle Throne Room N', 'Hyrule Castle Throne Room South Stairs']),
|
create_dungeon_region(player, 'Hyrule Castle Throne Room', 'A dungeon', None, ['Hyrule Castle Throne Room N', 'Hyrule Castle Throne Room South Stairs']),
|
||||||
|
|||||||
10
Rom.py
10
Rom.py
@@ -7,7 +7,7 @@ import random
|
|||||||
import struct
|
import struct
|
||||||
import subprocess
|
import subprocess
|
||||||
|
|
||||||
from BaseClasses import ShopType, Region, Location, Item
|
from BaseClasses import ShopType, Region, Location, Item, DoorType
|
||||||
from Dungeons import dungeon_music_addresses
|
from Dungeons import dungeon_music_addresses
|
||||||
from Text import MultiByteTextMapper, CompressedTextMapper, text_addresses, Credits, TextTable
|
from Text import MultiByteTextMapper, CompressedTextMapper, text_addresses, Credits, TextTable
|
||||||
from Text import Uncle_texts, Ganon1_texts, TavernMan_texts, Sahasrahla2_texts, Triforce_texts, Blind_texts, BombShop2_texts, junk_texts
|
from Text import Uncle_texts, Ganon1_texts, TavernMan_texts, Sahasrahla2_texts, Triforce_texts, Blind_texts, BombShop2_texts, junk_texts
|
||||||
@@ -532,7 +532,13 @@ def patch_rom(world, player, rom):
|
|||||||
rom.write_byte(0xDBB73 + exit.addresses, exit.target)
|
rom.write_byte(0xDBB73 + exit.addresses, exit.target)
|
||||||
if world.mode == 'inverted':
|
if world.mode == 'inverted':
|
||||||
patch_shuffled_dark_sanc(world, rom, player)
|
patch_shuffled_dark_sanc(world, rom, player)
|
||||||
|
|
||||||
|
# patch doors
|
||||||
|
if world.doorShuffle != 'vanilla':
|
||||||
|
for door in world.doors:
|
||||||
|
if door.dest is not None and door.player == player and door.type == DoorType.Normal:
|
||||||
|
rom.write_bytes(door.getAddress(), door.dest.getTarget(door.toggle))
|
||||||
|
|
||||||
write_custom_shops(rom, world, player)
|
write_custom_shops(rom, world, player)
|
||||||
|
|
||||||
# patch medallion requirements
|
# patch medallion requirements
|
||||||
|
|||||||
Reference in New Issue
Block a user