diff --git a/BaseClasses.py b/BaseClasses.py index 1c790d3f..ea4dda9e 100644 --- a/BaseClasses.py +++ b/BaseClasses.py @@ -886,6 +886,13 @@ class RegionChunk(object): self.unlinked_doors = set([]) +class Sector(object): + + def __init__(self): + self.regions = [] + self.oustandings_doors = [] + + class Boss(object): def __init__(self, name, enemizer_name, defeat_rule, player): self.name = name diff --git a/DoorShuffle.py b/DoorShuffle.py index d09bf76f..697d6f18 100644 --- a/DoorShuffle.py +++ b/DoorShuffle.py @@ -2,24 +2,26 @@ import random import collections import logging - -from BaseClasses import RegionType, DoorType, Direction, RegionChunk -from Items import ItemFactory - +from BaseClasses import RegionType, DoorType, Direction, RegionChunk, Sector +from Dungeons import hyrule_castle_regions, eastern_regions, desert_regions def link_doors(world, player): - # Make drop-down connections - if applicable + # Drop-down connections & push blocks for exitName, regionName in mandatory_connections: connect_simple_door(world, exitName, regionName, player) + # These should all be connected for now as normal connections + for edge_a, edge_b in intratile_doors: + connect_intertile_door(world, edge_a, edge_b, player) # These connection are here because they are currently unable to be shuffled - for entrance, ext in spiral_staircases: # these can now be shuffled, maybe - connect_two_way(world, entrance, ext, player, True) + if world.doorShuffle not in ['basic', 'experimental']: # these modes supports spirals + for entrance, ext in spiral_staircases: + connect_two_way(world, entrance, ext, player) for entrance, ext in straight_staircases: - connect_two_way(world, entrance, ext, player, True) + connect_two_way(world, entrance, ext, player) for entrance, ext in open_edges: - connect_two_way(world, entrance, ext, player, True) + connect_two_way(world, entrance, ext, player) for exitName, regionName in falldown_pits: connect_simple_door(world, exitName, regionName, player) for exitName, regionName in dungeon_warps: @@ -27,29 +29,19 @@ def link_doors(world, player): if world.doorShuffle == 'vanilla': for entrance, ext in default_door_connections: - connect_two_way(world, entrance, ext, player, True) + connect_two_way(world, entrance, ext, player) for ent, ext in default_one_way_connections: - connect_one_way(world, ent, ext, True) - normal_dungeon_pool(world, player) + connect_one_way(world, ent, ext, 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 - ES = world.get_dungeon('Hyrule Castle', player) - ES.small_keys = [ItemFactory('Small Key (Escape)', player)] - EP = world.get_dungeon('Eastern Palace', player) - EP.big_key = ItemFactory('Big Key (Eastern Palace)', player) + if world.doorShuffle != 'vanilla': + create_door_spoiler(world, player) def mark_regions(world, player): @@ -72,6 +64,31 @@ def mark_regions(world, player): queue.append(connected) # needs to be added +def create_door_spoiler(world, player): + logger = logging.getLogger('') + queue = collections.deque(world.doors) + while len(queue) > 0: + door_a = queue.popleft() + if door_a.type in [DoorType.Normal, DoorType.SpiralStairs]: + door_b = door_a.dest + if door_b is not None: + logger.info('spoiler: %s connected to %s', door_a.name, door_b.name) + if not door_a.blocked and not door_b.blocked: + world.spoiler.set_door(door_a.name, door_b.name, 'both', player) + elif door_a.blocked: + world.spoiler.set_door(door_b.name, door_a.name, 'entrance', player) + elif door_b.blocked: + world.spoiler.set_door(door_a.name, door_b.name, 'entrance', player) + else: + logger.warning('This is a bug') + if door_b in queue: + queue.remove(door_b) + else: + logger.info('Door not found in queue: %s connected to %s', door_b.name, door_a.name) + else: + logger.info('Door not connected: %s', door_a.name) + + # some useful functions def switch_dir(direction): oppositemap = { @@ -93,7 +110,21 @@ def connect_simple_door(world, exit_name, region_name, player): d.dest = region -def connect_two_way(world, entrancename, exitname, player, skipSpoiler=False): +def connect_intertile_door(world, edge_1, edge_2, player): + ent_a = world.get_entrance(edge_1, player) + ent_b = world.get_entrance(edge_2, player) + + # if these were already connected somewhere, remove the backreference + if ent_a.connected_region is not None: + ent_a.connected_region.entrances.remove(ent_a) + if ent_b.connected_region is not None: + ent_b.connected_region.entrances.remove(ent_b) + + ent_a.connect(ent_b.parent_region) + ent_b.connect(ent_a.parent_region) + + +def connect_two_way(world, entrancename, exitname, player): entrance = world.get_entrance(entrancename, player) ext = world.get_entrance(exitname, player) @@ -114,11 +145,9 @@ def connect_two_way(world, entrancename, exitname, player, skipSpoiler=False): x.dest = y if y is not None: y.dest = x - if not skipSpoiler and x is not None and y is not None: - world.spoiler.set_door(x.name, y.name, 'both', player) -def connect_one_way(world, entrancename, exitname, player, skipSpoiler=False): +def connect_one_way(world, entrancename, exitname, player): entrance = world.get_entrance(entrancename, player) ext = world.get_entrance(exitname, player) @@ -137,18 +166,14 @@ def connect_one_way(world, entrancename, exitname, player, skipSpoiler=False): x.dest = y if y is not None: y.dest = x - if not skipSpoiler and x is not None and y is not None: - world.spoiler.set_door(x.name, y.name, 'entrance', player) def within_dungeon(world, player): - # TODO: Add dungeon names to Regions so we can just look these lists up - dungeon_region_names_es = ['Hyrule Castle Lobby', 'Hyrule Castle West Lobby', 'Hyrule Castle East Lobby', 'Hyrule Castle East Hall', 'Hyrule Castle West Hall', 'Hyrule Castle Back Hall', 'Hyrule Castle Throne Room', 'Hyrule Dungeon Map Room', 'Hyrule Dungeon North Abyss', 'Hyrule Dungeon North Abyss Catwalk', 'Hyrule Dungeon South Abyss', 'Hyrule Dungeon South Abyss Catwalk', 'Hyrule Dungeon Guardroom', 'Hyrule Dungeon Armory', 'Hyrule Dungeon Staircase', 'Hyrule Dungeon Cellblock', 'Sewers Behind Tapestry', 'Sewers Rope Room', 'Sewers Dark Cross', 'Sewers Water', 'Sewers Key Rat', 'Sewers Secret Room', 'Sewers Secret Room Blocked Path', 'Sewers Pull Switch', 'Sanctuary'] - dungeon_region_names_ep = ['Eastern Lobby', 'Eastern Cannonball', 'Eastern Cannonball Ledge', 'Eastern Courtyard Ledge', 'Eastern Map Area', 'Eastern Compass Area', 'Eastern Courtyard', 'Eastern Fairies', 'Eastern Map Valley', 'Eastern Dark Square', 'Eastern Big Key', 'Eastern Darkness', 'Eastern Attic Start', 'Eastern Attic Switches', 'Eastern Eyegores', 'Eastern Boss'] - dungeon_region_lists = [dungeon_region_names_es, dungeon_region_names_ep] + dungeon_region_lists = [hyrule_castle_regions, eastern_regions, desert_regions] for region_list in dungeon_region_lists: shuffle_dungeon(world, player, region_list) + def shuffle_dungeon(world, player, dungeon_region_names): logger = logging.getLogger('') available_regions = [] @@ -183,9 +208,10 @@ def shuffle_dungeon(world, player, dungeon_region_names): else: # If there's no available region with a door, use an internal connection connect_door = find_compatible_door_in_list(world, door, available_doors, player) - logger.info(' Adding loop via %s', connect_door.name) - maybe_connect_two_way(world, door, connect_door, player) - available_doors.remove(connect_door) + if connect_door is not None: + logger.info(' Adding loop via %s', connect_door.name) + maybe_connect_two_way(world, door, connect_door, player) + available_doors.remove(connect_door) # Check that we used everything, and retry if we failed if len(available_regions) > 0 or len(available_doors) > 0: logger.info('Failed to add all regions to dungeon, trying again.') @@ -194,7 +220,7 @@ def shuffle_dungeon(world, player, dungeon_region_names): # Connects a and b. Or don't if they're an unsupported connection type. # TODO: This is gross, don't do it this way def maybe_connect_two_way(world, a, b, player): - if a.type == DoorType.Open or a.type == DoorType.StraightStairs or a.type == DoorType.Hole or a.type == DoorType.Warp: + if a.type in [DoorType.Open, DoorType.StraightStairs, DoorType.Hole, DoorType.Warp]: return connect_two_way(world, a.name, b.name, player) @@ -206,11 +232,13 @@ def find_compatible_door_in_regions(world, door, regions, player): return region, proposed_door return None, None + def find_compatible_door_in_list(world, door, doors, player): for proposed_door in doors: if doors_compatible(door, proposed_door): return proposed_door - + + def get_doors(world, region, player): res = [] for exit in region.exits: @@ -219,6 +247,7 @@ def get_doors(world, region, player): res.append(door) return res + def doors_compatible(a, b): if a.type != b.type: return False @@ -232,12 +261,14 @@ def doors_compatible(a, b): return doors_fit_mandatory_pair(dungeon_warps_as_doors, a, b) return a.direction == switch_dir(b.direction) + def doors_fit_mandatory_pair(pair_list, a, b): for pair_a, pair_b in pair_list: if (a.name == pair_a and b.name == pair_b) or (a.name == pair_b and b.name == pair_a): return True return False + # code below is an early prototype for cross-dungeon mode def cross_dungeon(world, player): logger = logging.getLogger('') @@ -650,32 +681,217 @@ def find_path(world, player, path, path_completion): queue.append(connected) return False + def experiment(world, player): - for ent, ext in experimental_connections: - if world.get_door(ent, player).blocked: - connect_one_way(world, ext, ent, player) - elif world.get_door(ext, player).blocked: - connect_one_way(world, ent, ext, player) - else: - connect_two_way(world, ent, ext, player) + hc = convert_to_sectors(hyrule_castle_regions, world, player) + ep = convert_to_sectors(eastern_regions, world, player) + dp = convert_to_sectors(desert_regions, world, player) + dungeon_sectors = [hc, ep, dp] + for sector_list in dungeon_sectors: + for sector in sector_list: + for region in sector.regions: + print(region.name) + for door in sector.oustandings_doors: + print(door.name) + print() + print() + + dungeon_region_lists = [hyrule_castle_regions, eastern_regions, desert_regions] + for region_list in dungeon_region_lists: + shuffle_dungeon_no_repeats(world, player, region_list) + # for ent, ext in experimental_connections: + # if world.get_door(ent, player).blocked: + # connect_one_way(world, ext, ent, player) + # elif world.get_door(ext, player).blocked: + # connect_one_way(world, ent, ext, player) + # else: + # connect_two_way(world, ent, ext, player) + + # Create list of regions + + +def convert_regions(region_names, world, player): + region_list = [] + for name in region_names: + region_list.append(world.get_region(name, player)) + return region_list + + +def convert_to_sectors(region_names, world, player): + region_list = convert_regions(region_names, world, player) + sectors = [] + while len(region_list) > 0: + region = region_list.pop() + region_chunk = [region] + exits = [] + exits.extend(region.exits) + outstanding_doors = [] + while len(exits) > 0: + ext = exits.pop() + if ext.connected_region is not None: + connect_region = ext.connected_region + if connect_region not in region_chunk and connect_region in region_list: + region_list.remove(connect_region) + region_chunk.append(connect_region) + exits.extend(connect_region.exits) + else: + door = world.check_for_door(ext.name, player) + if door is not None: + outstanding_doors.append(door) + sector = Sector() + sector.regions.extend(region_chunk) + sector.oustandings_doors.extend(outstanding_doors) + sectors.append(sector) + return sectors + + +def split_up_sectors(sector_list, entrance_sets): + new_sector_grid = [] + for entrance_set in entrance_sets: + new_sector_list = [] + for sector in sector_list: + s_regions = list(map(lambda r: r.name, sector.regions)) + for entrance in entrance_set: + if entrance in s_regions: + new_sector_list.append(sector) + break + new_sector_grid.append(new_sector_list) + # appalling I know - how to split up other things + return new_sector_grid + + + +# code below is for an algorithm without restarts + +# "simple" thing that would probably reduce the number of restarts: +# When you pick a region check for all existing connections to other regions +# first via region.exits (which is a list of non-door exits from the current region) +# then for each Entrance in that list it may have a connected_region (or not) +# but make sure the connected_region is a Dungeon type so the search doesn't venture out into the overworld. +# Then, once you have this region chunk, add all the doors and do the normal loop. +# Nuts, normal loop + + +def shuffle_dungeon_no_repeats(world, player, dungeon_region_names): + logger = logging.getLogger('') + available_regions = [] + for name in dungeon_region_names: + available_regions.append(world.get_region(name, player)) + random.shuffle(available_regions) + + available_doors = [] + # this is interesting but I want to ensure connectedness + # Except for Desert1/2 and Skull 1/2/3 - treat them as separate dungeons? + while len(available_regions) > 0: + # Pick a random region and make its doors the open set + region = available_regions.pop() + logger.info("Starting in %s", region.name) + regions = find_connected_regions(region, available_regions, logger) + for region in regions: + available_doors.extend(get_doors_ex(world, region, player)) + + # Loop until all available doors are used + while len(available_doors) > 0: + # Pick a random available door to connect + random.shuffle(available_doors) + door = available_doors.pop() + logger.info('Linking %s', door.name) + # Find an available region that has a compatible door + connect_region, connect_door = find_compatible_door_in_regions_ex(world, door, available_regions, player) + if connect_region is not None: + logger.info(' Found new region %s via %s', connect_region.name, connect_door.name) + # Apply connection and add the new region's doors to the available list + maybe_connect_two_way(world, door, connect_door, player) + c_regions = find_connected_regions(connect_region, available_regions, logger) + for region in c_regions: + available_doors.extend(get_doors_ex(world, region, player)) + # We've used this region and door, so don't use them again + available_doors.remove(connect_door) + available_regions.remove(connect_region) + else: + # If there's no available region with a door, use an internal connection + connect_door = find_compatible_door_in_list(world, door, available_doors, player) + if connect_door is not None: + logger.info(' Adding loop via %s', connect_door.name) + maybe_connect_two_way(world, door, connect_door, player) + available_doors.remove(connect_door) + # Check that we used everything, we failed otherwise + if len(available_regions) > 0 or len(available_doors) > 0: + logger.warning('Failed to add all regions/doors to dungeon, generation will likely fail.') + + +def find_connected_regions(region, available_regions, logger): + region_chunk = [region] + exits = [] + exits.extend(region.exits) + while len(exits) > 0: + ext = exits.pop() + if ext.connected_region is not None: + connect_region = ext.connected_region + if connect_region not in region_chunk and connect_region in available_regions: + # door = world.check_for_door(ext.name, player) + # if door is None or door.type not in [DoorType.Normal, DoorType.SpiralStairs]: + logger.info(' Found new region %s via %s', connect_region.name, ext.name) + available_regions.remove(connect_region) + region_chunk.append(connect_region) + exits.extend(connect_region.exits) + return region_chunk + + +def find_compatible_door_in_regions_ex(world, door, regions, player): + for region in regions: + for proposed_door in get_doors_ex(world, region, player): + if doors_compatible(door, proposed_door): + return region, proposed_door + return None, None + +def get_doors_ex(world, region, player): + res = [] + for exit in region.exits: + door = world.check_for_door(exit.name, player) + if door is not None and door.type in [DoorType.Normal, DoorType.SpiralStairs]: + res.append(door) + return res # DATA GOES DOWN HERE -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 N', 'Hyrule Dungeon Map Room'), - ('Sewers Secret Room Push Block', 'Sewers Secret Room Blocked Path') - ] +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 N', 'Hyrule Dungeon Map Room'), + ('Sewers Secret Room Push Block', 'Sewers Secret Room Blocked Path'), + ('Eastern Hint Tile Push Block', 'Eastern Compass Area') +] +intratile_doors = [ + ('Hyrule Dungeon Key Door S', 'Hyrule Dungeon Key Door N'), + ('Desert East Lobby WS', 'Desert East Wing ES'), + ('Desert East Wing Key Door EN', 'Desert Compass Key Door WN'), + ('Desert North Hall NW', 'Desert Map SW'), + ('Desert North Hall NE', 'Desert Map SE'), + ('Desert Sandworm Corner NE', 'Desert Bonk Torch SE'), + ('Desert Sandworm Corner WS', 'Desert Circle of Pots ES'), + ('Desert Circle of Pots NW', 'Desert Big Chest SW'), + ('Desert West Wing WS', 'Desert West Lobby ES',), + ('Desert Back Lobby NW', 'Desert Tiles 1 SW'), + ('Desert Bridge SW', 'Desert Four Statues NW'), + ('Desert Four Statues ES', 'Desert Beamos Hall WS',), + ('Desert Tiles 2 NE', 'Desert Wall Slide SE'), +] + +# todo: these path rules are more complicated I think... +# there may be a better way to do them if we randomize dungeon entrances dungeon_paths = { 'Hyrule Castle': [('Hyrule Castle Lobby', 'Hyrule Castle West Lobby'), ('Hyrule Castle Lobby', 'Hyrule Castle East Lobby'), - ('Hyrule Castle Lobby', 'Hyrule Dungeon Cellblock'), - ('Hyrule Dungeon Cellblock', 'Sanctuary')], + ('Hyrule Castle Lobby', 'Hyrule Dungeon Cellblock'), # just for standard mode? + ('Hyrule Dungeon Cellblock', 'Sanctuary')], # again, standard mode? 'Eastern Palace': [('Eastern Lobby', 'Eastern Boss')], - 'Desert Palace': [], + 'Desert Palace': [('Desert Main Lobby', 'Desert West Lobby'), + ('Desert Main Lobby', 'Desert East Lobby'), + ('Desert Back Lobby', 'Desert Boss')], # or Desert Main Lobby to Desert Boss would be fine I guess 'Tower of Hera': [], 'Agahnims Tower': [], 'Palace of Darkness': [], @@ -688,25 +904,31 @@ dungeon_paths = { 'Ganons Tower': [] } -open_edges = [('Hyrule Dungeon North Abyss Catwalk Dropdown', 'Hyrule Dungeon North Abyss'), - ('Hyrule Dungeon Key Door S', 'Hyrule Dungeon North Abyss'), - ('Hyrule Dungeon Key Door N', 'Hyrule Dungeon Map Room') - ] - spiral_staircases = [('Hyrule Castle Back Hall Down Stairs', 'Hyrule Dungeon Map Room Up Stairs'), ('Hyrule Dungeon Armory Down Stairs', 'Hyrule Dungeon Staircase Up Stairs'), ('Hyrule Dungeon Staircase Down Stairs', 'Hyrule Dungeon Cellblock Up Stairs'), ('Sewers Behind Tapestry Down Stairs', 'Sewers Rope Room Up Stairs'), ('Sewers Secret Room Up Stairs', 'Sewers Pull Switch Down Stairs'), - ('Eastern Darkness Up Stairs', 'Eastern Attic Start Down Stairs')] + ('Eastern Darkness Up Stairs', 'Eastern Attic Start Down Stairs'), + ('Desert Tiles 1 Up Stairs', 'Desert Bridge Down Stairs')] straight_staircases = [('Hyrule Castle Lobby North Stairs', 'Hyrule Castle Throne Room South Stairs'), ('Sewers Rope Room North Stairs', 'Sewers Dark Cross South Stairs')] -open_edges = [('Hyrule Dungeon North Abyss South Edge', 'Hyrule Dungeon South Abyss North Edge'), - ('Hyrule Dungeon North Abyss Catwalk Edge', 'Hyrule Dungeon South Abyss Catwalk North Edge'), - ('Hyrule Dungeon South Abyss West Edge', 'Hyrule Dungeon Guardroom Abyss Edge'), - ('Hyrule Dungeon South Abyss Catwalk West Edge', 'Hyrule Dungeon Guardroom Catwalk Edge')] +open_edges = [ + ('Hyrule Dungeon North Abyss South Edge', 'Hyrule Dungeon South Abyss North Edge'), + ('Hyrule Dungeon North Abyss Catwalk Edge', 'Hyrule Dungeon South Abyss Catwalk North Edge'), + ('Hyrule Dungeon South Abyss West Edge', 'Hyrule Dungeon Guardroom Abyss Edge'), + ('Hyrule Dungeon South Abyss Catwalk West Edge', 'Hyrule Dungeon Guardroom Catwalk Edge'), + ('Desert Main Lobby NW Edge', 'Desert North Hall SW Edge'), + ('Desert Main Lobby N Edge', 'Desert Dead End Edge'), + ('Desert Main Lobby NE Edge', 'Desert North Hall SE Edge'), + ('Desert Main Lobby E Edge', 'Desert East Wing W Edge'), + ('Desert East Wing N Edge', 'Desert Arrow Pot Corner S Edge'), + ('Desert Arrow Pot Corner W Edge', 'Desert North Hall E Edge'), + ('Desert North Hall W Edge', 'Desert Sandworm Corner S Edge'), + ('Desert Sandworm Corner E Edge', 'Desert West Wing N Edge') +] falldown_pits = [('Eastern Courtyard Potholes', 'Eastern Fairies')] falldown_pits_as_doors = [('Eastern Courtyard Potholes', 'Eastern Fairy Landing')] @@ -714,36 +936,42 @@ falldown_pits_as_doors = [('Eastern Courtyard Potholes', 'Eastern Fairy Landing' dungeon_warps = [('Eastern Fairies\' Warp', 'Eastern Courtyard')] dungeon_warps_as_doors = [('Eastern Fairies\' Warp', 'Eastern Courtyard Warp End')] -default_door_connections = [('Hyrule Castle Lobby W', 'Hyrule Castle West Lobby E'), - ('Hyrule Castle Lobby E', 'Hyrule Castle East Lobby W'), - ('Hyrule Castle Lobby WN', 'Hyrule Castle West Lobby EN'), - ('Hyrule Castle West Lobby N', 'Hyrule Castle West Hall S'), - ('Hyrule Castle East Lobby N', 'Hyrule Castle East Hall S'), - ('Hyrule Castle East Lobby NW', 'Hyrule Castle East Hall SW'), - ('Hyrule Castle East Hall W', 'Hyrule Castle Back Hall E'), - ('Hyrule Castle West Hall E', 'Hyrule Castle Back Hall W'), - ('Hyrule Castle Throne Room N', 'Sewers Behind Tapestry S'), - ('Hyrule Dungeon Guardroom N', 'Hyrule Dungeon Armory S'), - ('Sewers Dark Cross Key Door N', 'Sewers Dark Cross Key Door S'), - ('Sewers Water W', 'Sewers Key Rat E'), - ('Sewers Key Rat Key Door N', 'Sewers Secret Room Key Door S'), - ('Eastern Lobby N', 'Eastern Cannonball S'), - ('Eastern Cannonball N', 'Eastern Courtyard Ledge S'), - ('Eastern Cannonball Ledge WN', 'Eastern Big Key EN'), - ('Eastern Cannonball Ledge Key Door EN', 'Eastern Dark Square Key Door WN'), - ('Eastern Courtyard Ledge W', 'Eastern Compass Area E'), - ('Eastern Courtyard Ledge E', 'Eastern Map Area W'), - ('Eastern Compass Area EN', 'Eastern Courtyard WN'), - ('Eastern Courtyard EN', 'Eastern Map Valley WN'), - ('Eastern Courtyard N', 'Eastern Darkness S'), - ('Eastern Map Valley SW', 'Eastern Dark Square NW'), - ('Eastern Attic Start WS', 'Eastern Attic Switches ES'), - ('Eastern Attic Switches WS', 'Eastern Eyegores ES'), - ('Eastern Eyegores NE', 'Eastern Boss SE')] -# ('', ''), -default_one_way_connections = [('Sewers Pull Switch S', 'Sanctuary N'), - ('Eastern Big Key NE', 'Eastern Compass Area SW')] +default_door_connections = [ + ('Hyrule Castle Lobby W', 'Hyrule Castle West Lobby E'), + ('Hyrule Castle Lobby E', 'Hyrule Castle East Lobby W'), + ('Hyrule Castle Lobby WN', 'Hyrule Castle West Lobby EN'), + ('Hyrule Castle West Lobby N', 'Hyrule Castle West Hall S'), + ('Hyrule Castle East Lobby N', 'Hyrule Castle East Hall S'), + ('Hyrule Castle East Lobby NW', 'Hyrule Castle East Hall SW'), + ('Hyrule Castle East Hall W', 'Hyrule Castle Back Hall E'), + ('Hyrule Castle West Hall E', 'Hyrule Castle Back Hall W'), + ('Hyrule Castle Throne Room N', 'Sewers Behind Tapestry S'), + ('Hyrule Dungeon Guardroom N', 'Hyrule Dungeon Armory S'), + ('Sewers Dark Cross Key Door N', 'Sewers Dark Cross Key Door S'), + ('Sewers Water W', 'Sewers Key Rat E'), + ('Sewers Key Rat Key Door N', 'Sewers Secret Room Key Door S'), + ('Eastern Lobby N', 'Eastern Cannonball S'), + ('Eastern Cannonball N', 'Eastern Courtyard Ledge S'), + ('Eastern Cannonball Ledge WN', 'Eastern Big Key EN'), + ('Eastern Cannonball Ledge Key Door EN', 'Eastern Dark Square Key Door WN'), + ('Eastern Courtyard Ledge W', 'Eastern Compass Area E'), + ('Eastern Courtyard Ledge E', 'Eastern Map Area W'), + ('Eastern Compass Area EN', 'Eastern Courtyard WN'), + ('Eastern Courtyard EN', 'Eastern Map Valley WN'), + ('Eastern Courtyard N', 'Eastern Darkness S'), + ('Eastern Map Valley SW', 'Eastern Dark Square NW'), + ('Eastern Attic Start WS', 'Eastern Attic Switches ES'), + ('Eastern Attic Switches WS', 'Eastern Eyegores ES'), + ('Desert Compass NW', 'Desert Cannonball S'), + ('Desert Beamos Hall NE', 'Desert Tiles 2 SE') +] +# ('', ''), +default_one_way_connections = [ + ('Sewers Pull Switch S', 'Sanctuary N'), + ('Eastern Eyegores NE', 'Eastern Boss SE'), + ('Desert Wall Slide NW', 'Desert Boss SW') +] experimental_connections = [('Eastern Boss SE', 'Eastern Eyegores NE'), ('Eastern Eyegores ES', 'Eastern Map Valley WN'), @@ -782,3 +1010,9 @@ experimental_connections = [('Eastern Boss SE', 'Eastern Eyegores NE'), # ('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')] + + +desert_default_entrance_sets = [ + ['Desert Back Lobby'], + ['Desert Main Lobby', 'Desert West Lobby', 'Desert East Lobby'] +] diff --git a/Doors.py b/Doors.py index f3cd8af9..d109d4a1 100644 --- a/Doors.py +++ b/Doors.py @@ -22,7 +22,7 @@ HTL = 1 # High to Low 01 LTH = 2 # Low to High 10 LTL = 3 # Low to Low 11 - +# Only documenting non intratile transitions right now - could add intratile at some point def create_doors(world, player): world.doors += [ # hyrule castle @@ -94,7 +94,7 @@ def create_doors(world, player): create_dir_door(player, 'Eastern Map Area W', DoorType.Normal, Direction.West, 0xaa, Mid, High), create_dir_door(player, 'Eastern Compass Area E', DoorType.Normal, Direction.East, 0xa8, Mid, High), create_dir_door(player, 'Eastern Compass Area EN', DoorType.Normal, Direction.East, 0xa8, Top, Low), - create_blocked_door(player, 'Eastern Compass Area SW', DoorType.Normal, Direction.South, 0xa8, Right, High, False), + create_blocked_door(player, 'Eastern Compass Area SW', DoorType.Normal, Direction.South, 0xa8, Right, High), create_dir_door(player, 'Eastern Courtyard WN', DoorType.Normal, Direction.West, 0xa9, Top, Low), create_dir_door(player, 'Eastern Courtyard EN', DoorType.Normal, Direction.East, 0xa9, Top, Low), create_big_key_door(player, 'Eastern Courtyard N', DoorType.Normal, Direction.North, 0xa9, Mid, High), @@ -116,7 +116,33 @@ def create_doors(world, player): create_dir_door(player, 'Eastern Attic Switches WS', DoorType.Normal, Direction.West, 0xd9, Bot, High), create_dir_door(player, 'Eastern Eyegores ES', DoorType.Normal, Direction.East, 0xd8, Bot, High), create_dir_door(player, 'Eastern Eyegores NE', DoorType.Normal, Direction.North, 0xd8, Right, High), - create_dir_door(player, 'Eastern Boss SE', DoorType.Normal, Direction.South, 0xc8, Right, High), + create_blocked_door(player, 'Eastern Boss SE', DoorType.Normal, Direction.South, 0xc8, Right, High, False, 0x2), + + # Desert Palace + create_dir_door(player, 'Desert Main Lobby NW Edge', DoorType.Open, Direction.North, 0x84, None, High), + create_dir_door(player, 'Desert Main Lobby N Edge', DoorType.Open, Direction.North, 0x84, None, High), + create_dir_door(player, 'Desert Main Lobby NE Edge', DoorType.Open, Direction.North, 0x84, None, High), + create_dir_door(player, 'Desert Main Lobby E Edge', DoorType.Open, Direction.East, 0x84, None, High), + create_dir_door(player, 'Desert Dead End Edge', DoorType.Open, Direction.South, 0x74, None, High), + create_dir_door(player, 'Desert East Wing W Edge', DoorType.Open, Direction.West, 0x85, None, High), + create_dir_door(player, 'Desert East Wing N Edge', DoorType.Open, Direction.North, 0x85, None, High), + create_dir_door(player, 'Desert Compass NW', DoorType.Normal, Direction.North, 0x85, Left, High, 0x2), + create_dir_door(player, 'Desert Cannonball S', DoorType.Normal, Direction.South, 0x75, Left, High), + create_dir_door(player, 'Desert Arrow Pot Corner S Edge', DoorType.Open, Direction.South, 0x75, None, High), + create_dir_door(player, 'Desert Arrow Pot Corner W Edge', DoorType.Open, Direction.West, 0x75, None, High), + create_dir_door(player, 'Desert North Hall SE Edge', DoorType.Open, Direction.South, 0x74, None, High), + create_dir_door(player, 'Desert North Hall SW Edge', DoorType.Open, Direction.South, 0x74, None, High), + create_dir_door(player, 'Desert North Hall W Edge', DoorType.Open, Direction.West, 0x74, None, High), + create_dir_door(player, 'Desert North Hall E Edge', DoorType.Open, Direction.East, 0x74, None, High), + create_dir_door(player, 'Desert Sandworm Corner S Edge', DoorType.Open, Direction.South, 0x73, None, High), + create_dir_door(player, 'Desert Sandworm Corner E Edge', DoorType.Open, Direction.East, 0x73, None, High), + create_dir_door(player, 'Desert West Wing N Edge', DoorType.Open, Direction.North, 0x83, None, High), + create_spiral_stairs(player, 'Desert Tiles 1 Up Stairs', DoorType.SpiralStairs, Direction.Up, 0x63, 0, HTH, A, 0x1b, 0x6c, True), + create_spiral_stairs(player, 'Desert Bridge Down Stairs', DoorType.SpiralStairs, Direction.Down, 0x53, 0, HTH, A, 0x0f, 0x80, True), + create_dir_door(player, 'Desert Beamos Hall NE', DoorType.Normal, Direction.North, 0x53, Right, High), + create_dir_door(player, 'Desert Tiles 2 SE', DoorType.Normal, Direction.South, 0x43, Right, High), + create_big_key_door(player, 'Desert Wall Slide NW', DoorType.Normal, Direction.North, 0x43, Left, High), + create_blocked_door(player, 'Desert Boss SW', DoorType.Normal, Direction.South, 0x33, Left, High, False, 0x2), ] diff --git a/Dungeons.py b/Dungeons.py index f20f9fdc..3afa86f3 100644 --- a/Dungeons.py +++ b/Dungeons.py @@ -15,11 +15,11 @@ def create_dungeons(world, player): dungeon.world = world return dungeon - ES = make_dungeon('Hyrule Castle', None, ['Hyrule Castle Lobby', 'Hyrule Castle West Lobby', 'Hyrule Castle East Lobby', 'Sanctuary', 'Hyrule Dungeon Cellblock'], None, [], [ItemFactory('Map (Escape)', player)]) - EP = make_dungeon('Eastern Palace', 'Armos Knights', ['Eastern Lobby', 'Eastern Boss'], None, [], ItemFactory(['Map (Eastern Palace)', 'Compass (Eastern Palace)'], player)) + ES = make_dungeon('Hyrule Castle', None, hyrule_castle_regions, None, [ItemFactory('Small Key (Escape)', player)], [ItemFactory('Map (Escape)', player)]) + EP = make_dungeon('Eastern Palace', 'Armos Knights', eastern_regions, ItemFactory('Big Key (Eastern Palace)', player), [], ItemFactory(['Map (Eastern Palace)', 'Compass (Eastern Palace)'], player)) + DP = make_dungeon('Desert Palace', 'Lanmolas', desert_regions, ItemFactory('Big Key (Desert Palace)', player), [ItemFactory('Small Key (Desert Palace)', player)], ItemFactory(['Map (Desert Palace)', 'Compass (Desert Palace)'], player)) #still standard dungeons - DP = make_dungeon('Desert Palace', 'Lanmolas', ['Desert Palace North', 'Desert Palace Main (Inner)', 'Desert Palace Main (Outer)', 'Desert Palace East'], ItemFactory('Big Key (Desert Palace)', player), [ItemFactory('Small Key (Desert Palace)', player)], ItemFactory(['Map (Desert Palace)', 'Compass (Desert Palace)'], player)) ToH = make_dungeon('Tower of Hera', 'Moldorm', ['Tower of Hera (Bottom)', 'Tower of Hera (Basement)', 'Tower of Hera (Top)'], ItemFactory('Big Key (Tower of Hera)', player), [ItemFactory('Small Key (Tower of Hera)', player)], ItemFactory(['Map (Tower of Hera)', 'Compass (Tower of Hera)'], player)) PoD = make_dungeon('Palace of Darkness', 'Helmasaur King', ['Palace of Darkness (Entrance)', 'Palace of Darkness (Center)', 'Palace of Darkness (Big Key Chest)', 'Palace of Darkness (Bonk Section)', 'Palace of Darkness (North)', 'Palace of Darkness (Maze)', 'Palace of Darkness (Harmless Hellway)', 'Palace of Darkness (Final Section)'], ItemFactory('Big Key (Palace of Darkness)', player), ItemFactory(['Small Key (Palace of Darkness)'] * 6, player), ItemFactory(['Map (Palace of Darkness)', 'Compass (Palace of Darkness)'], player)) TT = make_dungeon('Thieves Town', 'Blind', ['Thieves Town (Entrance)', 'Thieves Town (Deep)', 'Blind Fight'], ItemFactory('Big Key (Thieves Town)', player), [ItemFactory('Small Key (Thieves Town)', player)], ItemFactory(['Map (Thieves Town)', 'Compass (Thieves Town)'], player)) @@ -166,3 +166,28 @@ dungeon_music_addresses = {'Eastern Palace - Prize': [0x1559A], 'Ice Palace - Prize': [0x155BF], 'Misery Mire - Prize': [0x155B9], 'Turtle Rock - Prize': [0x155C7, 0x155A7, 0x155AA, 0x155AB]} + +hyrule_castle_regions = [ + 'Hyrule Castle Lobby', 'Hyrule Castle West Lobby', 'Hyrule Castle East Lobby', 'Hyrule Castle East Hall', + 'Hyrule Castle West Hall', 'Hyrule Castle Back Hall', 'Hyrule Castle Throne Room', 'Hyrule Dungeon Map Room', + 'Hyrule Dungeon North Abyss', 'Hyrule Dungeon North Abyss Catwalk', 'Hyrule Dungeon South Abyss', + 'Hyrule Dungeon South Abyss Catwalk', 'Hyrule Dungeon Guardroom', 'Hyrule Dungeon Armory', + 'Hyrule Dungeon Staircase', 'Hyrule Dungeon Cellblock', 'Sewers Behind Tapestry', 'Sewers Rope Room', + 'Sewers Dark Cross', 'Sewers Water', 'Sewers Key Rat', 'Sewers Secret Room', 'Sewers Secret Room Blocked Path', + 'Sewers Pull Switch', 'Sanctuary' +] + +eastern_regions = [ + 'Eastern Lobby', 'Eastern Cannonball', 'Eastern Cannonball Ledge', 'Eastern Courtyard Ledge', 'Eastern Map Area', + 'Eastern Compass Area', 'Eastern Hint Tile Blocked Path', 'Eastern Courtyard', 'Eastern Fairies', + 'Eastern Map Valley', 'Eastern Dark Square', 'Eastern Big Key', 'Eastern Darkness', 'Eastern Attic Start', + 'Eastern Attic Switches', 'Eastern Eyegores', 'Eastern Boss' +] + +desert_regions = [ + 'Desert Main Lobby', 'Desert Dead End', 'Desert East Lobby', 'Desert East Wing', 'Desert Compass Room', + 'Desert Cannonball', 'Desert Arrow Pot Corner', 'Desert North Hall', 'Desert Map Room', 'Desert Sandworm Corner', + 'Desert Bonk Torch', 'Desert Circle of Pots', 'Desert Big Chest Room', 'Desert West Wing', + 'Desert West Lobby', 'Desert Back Lobby', 'Desert Tiles 1', + 'Desert Bridge', 'Desert Four Statues', 'Desert Beamos Hall', 'Desert Tiles 2', 'Desert Wall Slide', 'Desert Boss', +] diff --git a/EntranceShuffle.py b/EntranceShuffle.py index 46ad1c30..51373849 100644 --- a/EntranceShuffle.py +++ b/EntranceShuffle.py @@ -2837,7 +2837,6 @@ mandatory_connections = [('Lake Hylia Central Island Pier', 'Lake Hylia Central ('Kakariko Well (top to bottom)', 'Kakariko Well (bottom)'), ('Master Sword Meadow', 'Master Sword Meadow'), ('Hobo Bridge', 'Hobo Bridge'), - ('Desert Palace East Wing', 'Desert Palace East'), ('Bat Cave Drop Ledge', 'Bat Cave Drop Ledge'), ('Bat Cave Door', 'Bat Cave (left)'), ('Lost Woods Hideout (top to bottom)', 'Lost Woods Hideout (bottom)'), @@ -2953,8 +2952,6 @@ mandatory_connections = [('Lake Hylia Central Island Pier', 'Lake Hylia Central ('Skull Woods First Section (Top) One-Way Path', 'Skull Woods First Section'), ('Skull Woods Second Section (Drop)', 'Skull Woods Second Section'), ('Blind Fight', 'Blind Fight'), - ('Desert Palace Pots (Outer)', 'Desert Palace Main (Inner)'), - ('Desert Palace Pots (Inner)', 'Desert Palace Main (Outer)'), ('Ice Palace Entrance Room', 'Ice Palace (Main)'), ('Ice Palace (East)', 'Ice Palace (East)'), ('Ice Palace (East Top)', 'Ice Palace (East Top)'), @@ -3008,7 +3005,6 @@ inverted_mandatory_connections = [('Lake Hylia Central Island Pier', 'Lake Hylia ('Kakariko Well (top to bottom)', 'Kakariko Well (bottom)'), ('Master Sword Meadow', 'Master Sword Meadow'), ('Hobo Bridge', 'Hobo Bridge'), - ('Desert Palace East Wing', 'Desert Palace East'), ('Bat Cave Drop Ledge', 'Bat Cave Drop Ledge'), ('Bat Cave Door', 'Bat Cave (left)'), ('Lost Woods Hideout (top to bottom)', 'Lost Woods Hideout (bottom)'), @@ -3090,8 +3086,6 @@ inverted_mandatory_connections = [('Lake Hylia Central Island Pier', 'Lake Hylia ('Skull Woods First Section (Top) One-Way Path', 'Skull Woods First Section'), ('Skull Woods Second Section (Drop)', 'Skull Woods Second Section'), ('Blind Fight', 'Blind Fight'), - ('Desert Palace Pots (Outer)', 'Desert Palace Main (Inner)'), - ('Desert Palace Pots (Inner)', 'Desert Palace Main (Outer)'), ('Ice Palace Entrance Room', 'Ice Palace (Main)'), ('Ice Palace (East)', 'Ice Palace (East)'), ('Ice Palace (East Top)', 'Ice Palace (East Top)'), @@ -3517,10 +3511,10 @@ inverted_default_connections = [('Waterfall of Wishing', 'Waterfall of Wishing' ('Inverted Pyramid Entrance', 'Bottom of Pyramid')] # non shuffled dungeons -default_dungeon_connections = [('Desert Palace Entrance (South)', 'Desert Palace Main (Inner)'), - ('Desert Palace Entrance (West)', 'Desert Palace Main (Outer)'), - ('Desert Palace Entrance (North)', 'Desert Palace North'), - ('Desert Palace Entrance (East)', 'Desert Palace Main (Outer)'), +default_dungeon_connections = [('Desert Palace Entrance (South)', 'Desert Main Lobby'), + ('Desert Palace Entrance (West)', 'Desert West Lobby'), + ('Desert Palace Entrance (North)', 'Desert Back Lobby'), + ('Desert Palace Entrance (East)', 'Desert East Lobby'), ('Desert Palace Exit (South)', 'Desert Palace Stairs'), ('Desert Palace Exit (West)', 'Desert Ledge'), ('Desert Palace Exit (East)', 'Desert Palace Lone Stairs'), diff --git a/Regions.py b/Regions.py index 7bf297c0..54b859a5 100644 --- a/Regions.py +++ b/Regions.py @@ -94,11 +94,6 @@ def create_regions(world, player): create_lw_region(player, 'Desert Palace Stairs', None, ['Desert Palace Entrance (South)']), create_lw_region(player, 'Desert Palace Lone Stairs', None, ['Desert Palace Stairs Drop', 'Desert Palace Entrance (East)']), create_lw_region(player, 'Desert Palace Entrance (North) Spot', None, ['Desert Palace Entrance (North)', 'Desert Ledge Return Rocks']), - create_dungeon_region(player, 'Desert Palace Main (Outer)', 'Desert Palace', ['Desert Palace - Big Chest', 'Desert Palace - Torch', 'Desert Palace - Map Chest'], - ['Desert Palace Pots (Outer)', 'Desert Palace Exit (West)', 'Desert Palace Exit (East)', 'Desert Palace East Wing']), - create_dungeon_region(player, 'Desert Palace Main (Inner)', 'Desert Palace', None, ['Desert Palace Exit (South)', 'Desert Palace Pots (Inner)']), - create_dungeon_region(player, 'Desert Palace East', 'Desert Palace', ['Desert Palace - Compass Chest', 'Desert Palace - Big Key Chest']), - create_dungeon_region(player, 'Desert Palace North', 'Desert Palace', ['Desert Palace - Boss', 'Desert Palace - Prize'], ['Desert Palace Exit (North)']), create_lw_region(player, 'Master Sword Meadow', ['Master Sword Pedestal']), create_cave_region(player, 'Lost Woods Gamble', 'a game of chance'), create_lw_region(player, 'Hyrule Castle Courtyard', None, ['Hyrule Castle Secret Entrance Stairs', 'Hyrule Castle Entrance (South)']), @@ -312,29 +307,58 @@ def create_regions(world, player): create_dungeon_region(player, 'Sewers Dark Cross', 'A dungeon', ['Sewers - Dark Cross'], ['Sewers Dark Cross Key Door N', 'Sewers Dark Cross South Stairs']), create_dungeon_region(player, 'Sewers Water', 'A dungeon', None, ['Sewers Dark Cross Key Door S', 'Sewers Water W']), create_dungeon_region(player, 'Sewers Key Rat', 'A dungeon', None, ['Sewers Key Rat E', 'Sewers Key Rat Key Door N']), + create_dungeon_region(player, 'Sewers Secret Room Blocked Path', 'A dungeon', None, ['Sewers Secret Room Up Stairs']), create_dungeon_region(player, 'Sewers Secret Room', 'A dungeon', ['Sewers - Secret Room - Left', 'Sewers - Secret Room - Middle', 'Sewers - Secret Room - Right'], ['Sewers Secret Room Key Door S', 'Sewers Secret Room Push Block']), - create_dungeon_region(player, 'Sewers Secret Room Blocked Path', 'A dungeon', None, ['Sewers Secret Room Up Stairs']), create_dungeon_region(player, 'Sewers Pull Switch', 'A dungeon', None, ['Sewers Pull Switch Down Stairs', 'Sewers Pull Switch S']), create_dungeon_region(player, 'Sanctuary', 'A dungeon', ['Sanctuary'], ['Sanctuary Exit', 'Sanctuary N']), # Eastern Palace - create_dungeon_region(player, 'Eastern Lobby', 'A dungeon', None, ['Eastern Lobby N', 'Eastern Palace Exit']), - create_dungeon_region(player, 'Eastern Cannonball', 'A dungeon', ['Eastern Palace - Cannonball Chest'], ['Eastern Cannonball S', 'Eastern Cannonball N']), - create_dungeon_region(player, 'Eastern Cannonball Ledge', 'A dungeon', None, ['Eastern Cannonball Ledge WN', 'Eastern Cannonball Ledge Key Door EN']), - create_dungeon_region(player, 'Eastern Courtyard Ledge', 'A dungeon', None, ['Eastern Courtyard Ledge S', 'Eastern Courtyard Ledge W', 'Eastern Courtyard Ledge E']), - create_dungeon_region(player, 'Eastern Map Area', 'A dungeon', ['Eastern Palace - Map Chest'], ['Eastern Map Area W']), - create_dungeon_region(player, 'Eastern Compass Area', 'A dungeon', ['Eastern Palace - Compass Chest'], ['Eastern Compass Area E', 'Eastern Compass Area EN', 'Eastern Compass Area SW']), - create_dungeon_region(player, 'Eastern Courtyard', 'A dungeon', ['Eastern Palace - Big Chest'], ['Eastern Courtyard WN', 'Eastern Courtyard EN', 'Eastern Courtyard N', 'Eastern Courtyard Potholes', 'Eastern Courtyard Warp End']), - create_dungeon_region(player, 'Eastern Fairies', 'A dungeon', None, ['Eastern Fairies\' Warp', 'Eastern Fairy Landing']), - create_dungeon_region(player, 'Eastern Map Valley', 'A dungeon', None, ['Eastern Map Valley WN', 'Eastern Map Valley SW']), - create_dungeon_region(player, 'Eastern Dark Square', 'A dungeon', None, ['Eastern Dark Square NW', 'Eastern Dark Square Key Door WN']), - create_dungeon_region(player, 'Eastern Big Key', 'A dungeon', ['Eastern Palace - Big Key Chest'], ['Eastern Big Key EN', 'Eastern Big Key NE']), - create_dungeon_region(player, 'Eastern Darkness', 'A dungeon', None, ['Eastern Darkness S', 'Eastern Darkness Up Stairs']), - create_dungeon_region(player, 'Eastern Attic Start', 'A dungeon', None, ['Eastern Attic Start Down Stairs', 'Eastern Attic Start WS']), - create_dungeon_region(player, 'Eastern Attic Switches', 'A dungeon', None, ['Eastern Attic Switches ES', 'Eastern Attic Switches WS']), - create_dungeon_region(player, 'Eastern Eyegores', 'A dungeon', None, ['Eastern Eyegores ES', 'Eastern Eyegores NE']), - create_dungeon_region(player, 'Eastern Boss', 'A dungeon', ['Eastern Palace - Boss', 'Eastern Palace - Prize'], ['Eastern Boss SE']), + create_dungeon_region(player, 'Eastern Lobby', 'Eastern Palace', None, ['Eastern Lobby N', 'Eastern Palace Exit']), + create_dungeon_region(player, 'Eastern Cannonball', 'Eastern Palace', ['Eastern Palace - Cannonball Chest'], ['Eastern Cannonball S', 'Eastern Cannonball N']), + create_dungeon_region(player, 'Eastern Cannonball Ledge', 'Eastern Palace', None, ['Eastern Cannonball Ledge WN', 'Eastern Cannonball Ledge Key Door EN']), + create_dungeon_region(player, 'Eastern Courtyard Ledge', 'Eastern Palace', None, ['Eastern Courtyard Ledge S', 'Eastern Courtyard Ledge W', 'Eastern Courtyard Ledge E']), + create_dungeon_region(player, 'Eastern Map Area', 'Eastern Palace', ['Eastern Palace - Map Chest'], ['Eastern Map Area W']), + create_dungeon_region(player, 'Eastern Compass Area', 'Eastern Palace', ['Eastern Palace - Compass Chest'], ['Eastern Compass Area E', 'Eastern Compass Area EN']), + create_dungeon_region(player, 'Eastern Hint Tile Blocked Path', 'Eastern Palace', None, ['Eastern Compass Area SW', 'Eastern Hint Tile Push Block']), + create_dungeon_region(player, 'Eastern Courtyard', 'Eastern Palace', ['Eastern Palace - Big Chest'], ['Eastern Courtyard WN', 'Eastern Courtyard EN', 'Eastern Courtyard N', 'Eastern Courtyard Potholes', 'Eastern Courtyard Warp End']), + create_dungeon_region(player, 'Eastern Fairies', 'Eastern Palace', None, ['Eastern Fairies\' Warp', 'Eastern Fairy Landing']), + create_dungeon_region(player, 'Eastern Map Valley', 'Eastern Palace', None, ['Eastern Map Valley WN', 'Eastern Map Valley SW']), + create_dungeon_region(player, 'Eastern Dark Square', 'Eastern Palace', None, ['Eastern Dark Square NW', 'Eastern Dark Square Key Door WN']), + create_dungeon_region(player, 'Eastern Big Key', 'Eastern Palace', ['Eastern Palace - Big Key Chest'], ['Eastern Big Key EN', 'Eastern Big Key NE']), + create_dungeon_region(player, 'Eastern Darkness', 'Eastern Palace', None, ['Eastern Darkness S', 'Eastern Darkness Up Stairs']), + create_dungeon_region(player, 'Eastern Attic Start', 'Eastern Palace', None, ['Eastern Attic Start Down Stairs', 'Eastern Attic Start WS']), + create_dungeon_region(player, 'Eastern Attic Switches', 'Eastern Palace', None, ['Eastern Attic Switches ES', 'Eastern Attic Switches WS']), + create_dungeon_region(player, 'Eastern Eyegores', 'Eastern Palace', None, ['Eastern Eyegores ES', 'Eastern Eyegores NE']), + create_dungeon_region(player, 'Eastern Boss', 'Eastern Palace', ['Eastern Palace - Boss', 'Eastern Palace - Prize'], ['Eastern Boss SE']), + + # Desert Palace + # note for later: pots in desert keep out the bunny - logically (though not practically b/c of dungeon bunny revival) + create_dungeon_region(player, 'Desert Main Lobby', 'Desert Palace', None, ['Desert Palace Exit (South)','Desert Main Lobby NW Edge', 'Desert Main Lobby N Edge', 'Desert Main Lobby NE Edge', 'Desert Main Lobby E Edge']), + create_dungeon_region(player, 'Desert Dead End', 'Desert Palace', None, ['Desert Dead End Edge']), + create_dungeon_region(player, 'Desert East Lobby', 'Desert Palace', None, ['Desert East Lobby WS', 'Desert Palace Exit (East)']), + create_dungeon_region(player, 'Desert East Wing', 'Desert Palace', None, ['Desert East Wing ES', 'Desert East Wing Key Door EN', 'Desert East Wing W Edge', 'Desert East Wing N Edge']), + create_dungeon_region(player, 'Desert Compass Room', 'Desert Palace', ['Desert Palace - Compass Chest'], ['Desert Compass Key Door WN', 'Desert Compass NW']), + create_dungeon_region(player, 'Desert Cannonball', 'Desert Palace', ['Desert Palace - Big Key Chest'], ['Desert Cannonball S']), + create_dungeon_region(player, 'Desert Arrow Pot Corner', 'Desert Palace', None, ['Desert Arrow Pot Corner S Edge', 'Desert Arrow Pot Corner W Edge']), + # skip the trap room for now + create_dungeon_region(player, 'Desert North Hall', 'Desert Palace', None, ['Desert North Hall SE Edge', 'Desert North Hall SW Edge', 'Desert North Hall W Edge', 'Desert North Hall E Edge', 'Desert North Hall NW', 'Desert North Hall NE']), + create_dungeon_region(player, 'Desert Map Room', 'Desert Palace', ['Desert Palace - Map Chest'], ['Desert Map SW', 'Desert Map SE']), + create_dungeon_region(player, 'Desert Sandworm Corner', 'Desert Palace', None, ['Desert Sandworm Corner S Edge', 'Desert Sandworm Corner E Edge', 'Desert Sandworm Corner NE', 'Desert Sandworm Corner WS']), + create_dungeon_region(player, 'Desert Bonk Torch', 'Desert Palace', ['Desert Palace - Torch'], ['Desert Bonk Torch SE']), + create_dungeon_region(player, 'Desert Circle of Pots', 'Desert Palace', None, ['Desert Circle of Pots ES', 'Desert Circle of Pots NW']), + create_dungeon_region(player, 'Desert Big Chest Room', 'Desert Palace', ['Desert Palace - Big Chest'], ['Desert Big Chest SW']), + create_dungeon_region(player, 'Desert West Wing', 'Desert Palace', None, ['Desert West Wing N Edge', 'Desert West Wing WS']), + create_dungeon_region(player, 'Desert West Lobby', 'Desert Palace', None, ['Desert West Lobby ES', 'Desert Palace Exit (West)']), + # skipping the fairy room for now + create_dungeon_region(player, 'Desert Back Lobby', 'Desert Palace', None, ['Desert Palace Exit (North)', 'Desert Back Lobby NW']), + create_dungeon_region(player, 'Desert Tiles 1', 'Desert Palace', None, ['Desert Tiles 1 SW', 'Desert Tiles 1 Up Stairs']), + create_dungeon_region(player, 'Desert Bridge', 'Desert Palace', None, ['Desert Bridge Down Stairs', 'Desert Bridge SW']), + create_dungeon_region(player, 'Desert Four Statues', 'Desert Palace', None, ['Desert Four Statues NW', 'Desert Four Statues ES']), + create_dungeon_region(player, 'Desert Beamos Hall', 'Desert Palace', None, ['Desert Beamos Hall WS', 'Desert Beamos Hall NE']), + create_dungeon_region(player, 'Desert Tiles 2', 'Desert Palace', None, ['Desert Tiles 2 SE', 'Desert Tiles 2 NE']), + create_dungeon_region(player, 'Desert Wall Slide', 'Desert Palace', None, ['Desert Wall Slide SE', 'Desert Wall Slide NW']), + create_dungeon_region(player, 'Desert Boss', 'Desert Palace', ['Desert Palace - Boss', 'Desert Palace - Prize'], ['Desert Boss SW']), # pod # tt @@ -345,7 +369,6 @@ def create_regions(world, player): # gt # sw - # desert # hera # AgaTower ] diff --git a/Rules.py b/Rules.py index 772b2def..44270b21 100644 --- a/Rules.py +++ b/Rules.py @@ -269,7 +269,7 @@ def global_rules(world, player): set_rule(world.get_location('Desert Palace - Big Chest', player), lambda state: state.has('Big Key (Desert Palace)', player)) set_rule(world.get_location('Desert Palace - Torch', player), lambda state: state.has_Boots(player)) - set_rule(world.get_entrance('Desert Palace East Wing', player), lambda state: state.has_key('Small Key (Desert Palace)', player)) + # set_rule(world.get_entrance('Desert Palace East Wing', player), lambda state: state.has_key('Small Key (Desert Palace)', player)) set_rule(world.get_location('Desert Palace - Prize', player), lambda state: state.has_key('Small Key (Desert Palace)', player) and state.has('Big Key (Desert Palace)', player) and state.has_fire_source(player) and world.get_location('Desert Palace - Prize', player).parent_region.dungeon.boss.can_defeat(state)) set_rule(world.get_location('Desert Palace - Boss', player), lambda state: state.has_key('Small Key (Desert Palace)', player) and state.has('Big Key (Desert Palace)', player) and state.has_fire_source(player) and world.get_location('Desert Palace - Boss', player).parent_region.dungeon.boss.can_defeat(state)) for location in ['Desert Palace - Boss', 'Desert Palace - Big Chest']: @@ -1480,8 +1480,10 @@ def set_bunny_rules(world, player): # regions for the exits of multi-entrace caves/drops that bunny cannot pass # Note spiral cave may be technically passible, but it would be too absurd to require since OHKO mode is a thing. bunny_impassable_caves = ['Bumper Cave', 'Two Brothers House', 'Hookshot Cave', 'Skull Woods First Section (Right)', 'Skull Woods First Section (Left)', 'Skull Woods First Section (Top)', 'Turtle Rock (Entrance)', 'Turtle Rock (Second Section)', 'Turtle Rock (Big Chest)', 'Skull Woods Second Section (Drop)', - 'Turtle Rock (Eye Bridge)', 'Pyramid', 'Spiral Cave (Top)', 'Desert Palace Main (Inner)', 'Fairy Ascension Cave (Drop)'] - # todo: bunny impassable caves - sewers drop may or may not be - maybe just new terminology + 'Turtle Rock (Eye Bridge)', 'Pyramid', 'Spiral Cave (Top)', 'Fairy Ascension Cave (Drop)'] + # todo: bunny impassable caves + # sewers drop may or may not be - maybe just new terminology + # desert pots are impassible by bunny - need rules for those transitions bunny_accessible_locations = ['Link\'s Uncle', 'Sahasrahla', 'Sick Kid', 'Lost Woods Hideout', 'Lumberjack Tree', 'Checkerboard Cave', 'Potion Shop', 'Spectacle Rock Cave', 'Pyramid', 'Hype Cave - Generous Guy', 'Peg Cave', 'Bumper Cave Ledge', 'Dark Blacksmith Ruins']