Aga Tower preliminary check in
This commit is contained in:
@@ -752,14 +752,8 @@ class Dungeon(object):
|
|||||||
self.bosses = dict()
|
self.bosses = dict()
|
||||||
self.player = player
|
self.player = player
|
||||||
self.world = None
|
self.world = None
|
||||||
self.paths = None
|
|
||||||
self.path_completion = dict()
|
|
||||||
self.key_number = len(small_keys)
|
|
||||||
self.big_key_required = True if self.big_key else False
|
|
||||||
self.chunks = list()
|
|
||||||
|
|
||||||
self.unlinked_doors = set([])
|
self.entrance_regions = []
|
||||||
self.chests = 0
|
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def boss(self):
|
def boss(self):
|
||||||
@@ -861,12 +855,10 @@ class Door(object):
|
|||||||
# logical properties
|
# logical properties
|
||||||
# self.connected = False # combine with Dest?
|
# self.connected = False # combine with Dest?
|
||||||
self.dest = None
|
self.dest = None
|
||||||
self.parentChunk = None
|
|
||||||
self.blocked = False # Indicates if the door is normally blocked off. (Sanc door or always closed)
|
self.blocked = False # Indicates if the door is normally blocked off. (Sanc door or always closed)
|
||||||
self.smallKey = False # There's a small key door on this side
|
self.smallKey = False # There's a small key door on this side
|
||||||
self.bigKey = False # There's a big key door on this side
|
self.bigKey = False # There's a big key door on this side
|
||||||
self.ugly = False # Indicates that it can't be seen from the front (e.g. back of a big key door)
|
self.ugly = False # Indicates that it can't be seen from the front (e.g. back of a big key door)
|
||||||
self.landing = False
|
|
||||||
|
|
||||||
def getAddress(self):
|
def getAddress(self):
|
||||||
if self.type == DoorType.Normal:
|
if self.type == DoorType.Normal:
|
||||||
@@ -904,17 +896,15 @@ class Sector(object):
|
|||||||
def polarity(self):
|
def polarity(self):
|
||||||
polarity = [0, 0, 0]
|
polarity = [0, 0, 0]
|
||||||
for door in self.outstanding_doors:
|
for door in self.outstanding_doors:
|
||||||
if not door.landing:
|
idx, inc = pol_idx[door.direction]
|
||||||
idx, inc = pol_idx[door.direction]
|
polarity[idx] = pol_inc[inc](polarity[idx])
|
||||||
polarity[idx] = pol_inc[inc](polarity[idx])
|
|
||||||
return polarity
|
return polarity
|
||||||
|
|
||||||
def magnitude(self):
|
def magnitude(self):
|
||||||
magnitude = [0, 0, 0]
|
magnitude = [0, 0, 0]
|
||||||
for door in self.outstanding_doors:
|
for door in self.outstanding_doors:
|
||||||
if not door.landing:
|
idx, inc = pol_idx[door.direction]
|
||||||
idx, inc = pol_idx[door.direction]
|
magnitude[idx] = magnitude[idx] + 1
|
||||||
magnitude[idx] = magnitude[idx] + 1
|
|
||||||
return magnitude
|
return magnitude
|
||||||
|
|
||||||
def outflow(self):
|
def outflow(self):
|
||||||
|
|||||||
256
DoorShuffle.py
256
DoorShuffle.py
@@ -3,7 +3,8 @@ import collections
|
|||||||
import logging
|
import logging
|
||||||
|
|
||||||
from BaseClasses import RegionType, DoorType, Direction, Sector, pol_idx
|
from BaseClasses import RegionType, DoorType, Direction, Sector, pol_idx
|
||||||
from Dungeons import hyrule_castle_regions, eastern_regions, desert_regions, hera_regions
|
from Dungeons import hyrule_castle_regions, eastern_regions, desert_regions, hera_regions, tower_regions
|
||||||
|
from Dungeons import dungeon_regions
|
||||||
|
|
||||||
def link_doors(world, player):
|
def link_doors(world, player):
|
||||||
|
|
||||||
@@ -14,7 +15,7 @@ def link_doors(world, player):
|
|||||||
for edge_a, edge_b in interior_doors:
|
for edge_a, edge_b in interior_doors:
|
||||||
connect_two_way(world, edge_a, edge_b, player)
|
connect_two_way(world, edge_a, edge_b, player)
|
||||||
|
|
||||||
# These connection are here because they are currently unable to be shuffled
|
# These connections are here because they are currently unable to be shuffled
|
||||||
for entrance, ext in straight_staircases:
|
for entrance, ext in straight_staircases:
|
||||||
connect_two_way(world, entrance, ext, player)
|
connect_two_way(world, entrance, ext, player)
|
||||||
for entrance, ext in open_edges:
|
for entrance, ext in open_edges:
|
||||||
@@ -161,11 +162,13 @@ def within_dungeon(world, player):
|
|||||||
dungeon_region_starts_ep = ['Eastern Lobby']
|
dungeon_region_starts_ep = ['Eastern Lobby']
|
||||||
dungeon_region_starts_dp = ['Desert Back Lobby', 'Desert Main Lobby', 'Desert West Lobby', 'Desert East Lobby']
|
dungeon_region_starts_dp = ['Desert Back Lobby', 'Desert Main Lobby', 'Desert West Lobby', 'Desert East Lobby']
|
||||||
dungeon_region_starts_th = ['Hera Lobby']
|
dungeon_region_starts_th = ['Hera Lobby']
|
||||||
|
dungeon_region_starts_at = ['Tower Lobby']
|
||||||
dungeon_region_lists = [
|
dungeon_region_lists = [
|
||||||
(dungeon_region_starts_es, hyrule_castle_regions),
|
(dungeon_region_starts_es, hyrule_castle_regions),
|
||||||
(dungeon_region_starts_ep, eastern_regions),
|
(dungeon_region_starts_ep, eastern_regions),
|
||||||
(dungeon_region_starts_dp, desert_regions),
|
(dungeon_region_starts_dp, desert_regions),
|
||||||
(dungeon_region_starts_th, hera_regions)
|
(dungeon_region_starts_th, hera_regions),
|
||||||
|
(dungeon_region_starts_at, tower_regions),
|
||||||
]
|
]
|
||||||
for start_list, region_list in dungeon_region_lists:
|
for start_list, region_list in dungeon_region_lists:
|
||||||
shuffle_dungeon(world, player, start_list, region_list)
|
shuffle_dungeon(world, player, start_list, region_list)
|
||||||
@@ -199,7 +202,7 @@ def shuffle_dungeon(world, player, start_region_names, dungeon_region_names):
|
|||||||
# into the dungeon), or puts them late in the dungeon (so they probably are part
|
# into the dungeon), or puts them late in the dungeon (so they probably are part
|
||||||
# of a loop). Panic if neither of these happens.
|
# of a loop). Panic if neither of these happens.
|
||||||
random.shuffle(available_doors)
|
random.shuffle(available_doors)
|
||||||
available_doors.sort(key=lambda door: 1 if door.blocked else 2 if door.ugly else 0)
|
available_doors.sort(key=lambda door: 1 if door.blocked else 0 if door.ugly else 2)
|
||||||
door = available_doors.pop()
|
door = available_doors.pop()
|
||||||
logger.info('Linking %s', door.name)
|
logger.info('Linking %s', door.name)
|
||||||
# Find an available region that has a compatible door
|
# Find an available region that has a compatible door
|
||||||
@@ -328,28 +331,39 @@ def doors_fit_mandatory_pair(pair_list, a, b):
|
|||||||
|
|
||||||
|
|
||||||
def cross_dungeon(world, player):
|
def cross_dungeon(world, player):
|
||||||
hc = convert_to_sectors(hyrule_castle_regions, world, player)
|
hc = convert_to_sectors(dungeon_regions['Hyrule Castle'], world, player)
|
||||||
ep = convert_to_sectors(eastern_regions, world, player)
|
ep = convert_to_sectors(dungeon_regions['Eastern'], world, player)
|
||||||
dp = convert_to_sectors(desert_regions, world, player)
|
dp = convert_to_sectors(dungeon_regions['Desert'], world, player)
|
||||||
th = convert_to_sectors(hera_regions, world, player)
|
th = convert_to_sectors(dungeon_regions['Hera'], world, player)
|
||||||
world_split = split_up_sectors(hc + ep + dp + th, default_dungeon_sets)
|
at = convert_to_sectors(dungeon_regions['Tower'], world, player)
|
||||||
dp_split = split_up_sectors(world_split.pop(2), desert_default_entrance_sets)
|
dungeon_split = split_up_sectors(hc + ep + dp + th + at, default_dungeon_sets)
|
||||||
world_split.extend(dp_split)
|
dp_split = split_up_sectors(dungeon_split.pop(2), desert_default_entrance_sets)
|
||||||
|
dungeon_sectors = []
|
||||||
# todo - adjust dungeon item pools
|
# todo - adjust dungeon item pools
|
||||||
for sector_list in world_split:
|
for idx, sector_list in enumerate(dungeon_split):
|
||||||
shuffle_dungeon_no_repeats(world, player, sector_list)
|
dungeon_sectors.append((sector_list, entrance_sets[idx]))
|
||||||
|
for idx, sector_list in enumerate(dp_split):
|
||||||
|
dungeon_sectors.append((sector_list, desert_default_entrance_sets[idx]))
|
||||||
|
|
||||||
|
for sector_list, entrance_list in dungeon_sectors:
|
||||||
|
shuffle_dungeon_no_repeats(world, player, sector_list, entrance_list)
|
||||||
|
|
||||||
|
|
||||||
def experiment(world, player):
|
def experiment(world, player):
|
||||||
hc = convert_to_sectors(hyrule_castle_regions, world, player)
|
hc = convert_to_sectors(dungeon_regions['Hyrule Castle'], world, player)
|
||||||
ep = convert_to_sectors(eastern_regions, world, player)
|
ep = convert_to_sectors(dungeon_regions['Eastern'], world, player)
|
||||||
dp = convert_to_sectors(desert_regions, world, player)
|
dp = convert_to_sectors(dungeon_regions['Desert'], world, player)
|
||||||
th = convert_to_sectors(hera_regions, world, player)
|
th = convert_to_sectors(dungeon_regions['Hera'], world, player)
|
||||||
dungeon_sectors = [hc, ep, th]
|
at = convert_to_sectors(dungeon_regions['Tower'], world, player)
|
||||||
|
dungeon_sectors = []
|
||||||
|
for idx, sector_list in enumerate([hc, ep, th, at]):
|
||||||
|
dungeon_sectors.append((sector_list, entrance_sets[idx]))
|
||||||
dp_split = split_up_sectors(dp, desert_default_entrance_sets)
|
dp_split = split_up_sectors(dp, desert_default_entrance_sets)
|
||||||
dungeon_sectors.extend(dp_split)
|
for idx, sector_list in enumerate(dp_split):
|
||||||
for sector_list in dungeon_sectors:
|
dungeon_sectors.append((sector_list, desert_default_entrance_sets[idx]))
|
||||||
shuffle_dungeon_no_repeats(world, player, sector_list)
|
|
||||||
|
for sector_list, entrance_list in dungeon_sectors:
|
||||||
|
shuffle_dungeon_no_repeats(world, player, sector_list, entrance_list)
|
||||||
|
|
||||||
|
|
||||||
def convert_regions(region_names, world, player):
|
def convert_regions(region_names, world, player):
|
||||||
@@ -378,7 +392,7 @@ def convert_to_sectors(region_names, world, player):
|
|||||||
exits.extend(connect_region.exits)
|
exits.extend(connect_region.exits)
|
||||||
else:
|
else:
|
||||||
door = world.check_for_door(ext.name, player)
|
door = world.check_for_door(ext.name, player)
|
||||||
if door is not None and not door.landing:
|
if door is not None:
|
||||||
outstanding_doors.append(door)
|
outstanding_doors.append(door)
|
||||||
sector = Sector()
|
sector = Sector()
|
||||||
sector.regions.extend(region_chunk)
|
sector.regions.extend(region_chunk)
|
||||||
@@ -515,79 +529,111 @@ def find_proposal(proposal, buckets, candidates):
|
|||||||
|
|
||||||
# code below is for an algorithm without restarts
|
# code below is for an algorithm without restarts
|
||||||
|
|
||||||
# "simple" thing that would probably reduce the number of restarts:
|
def shuffle_dungeon_no_repeats(world, player, available_sectors, entrance_region_names):
|
||||||
# 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, available_sectors):
|
|
||||||
logger = logging.getLogger('')
|
logger = logging.getLogger('')
|
||||||
|
|
||||||
random.shuffle(available_sectors)
|
random.shuffle(available_sectors)
|
||||||
for sector in available_sectors:
|
for sector in available_sectors:
|
||||||
random.shuffle(sector.outstanding_doors)
|
random.shuffle(sector.outstanding_doors)
|
||||||
|
|
||||||
while len(available_sectors) > 0:
|
entrance_regions = []
|
||||||
# Pick a random region and make its doors the open set
|
# current_sector = None
|
||||||
sector = available_sectors.pop()
|
for region_name in entrance_region_names:
|
||||||
current_sector = sector
|
entrance_regions.append(world.get_region(region_name, player))
|
||||||
|
|
||||||
# Loop until all available doors are used
|
reachable_doors, visited_regions = extend_reachable(entrance_regions, [], world, player)
|
||||||
while len(current_sector.outstanding_doors) > 0:
|
# Loop until all available doors are used
|
||||||
# Pick a random available door to connect
|
while len(reachable_doors) > 0:
|
||||||
random.shuffle(current_sector.outstanding_doors)
|
# Pick a random available door to connect
|
||||||
door = current_sector.outstanding_doors.pop()
|
door = random.choice(reachable_doors)
|
||||||
logger.info('Linking %s', door.name)
|
sector = find_sector_for_door(door, available_sectors)
|
||||||
# Find an available region that has a compatible door
|
sector.outstanding_doors.remove(door)
|
||||||
compatibles = find_all_compatible_door_in_sectors_ex(door, available_sectors)
|
# door_connected = False
|
||||||
while len(compatibles) > 0:
|
logger.info('Linking %s', door.name)
|
||||||
connect_sector, connect_door = compatibles.pop()
|
# Find an available region that has a compatible door
|
||||||
logger.info(' Found possible new sector via %s', connect_door.name)
|
compatibles = find_all_compatible_door_in_sectors_ex(door, available_sectors, reachable_doors)
|
||||||
# Check if valid
|
while len(compatibles) > 0:
|
||||||
if is_valid(door, connect_door, current_sector, connect_sector, available_sectors):
|
connect_sector, connect_door = compatibles.pop()
|
||||||
# Apply connection and add the new region's doors to the available list
|
logger.info(' Found possible new sector via %s', connect_door.name)
|
||||||
maybe_connect_two_way(world, door, connect_door, player)
|
# Check if valid
|
||||||
connect_sector.outstanding_doors.remove(connect_door)
|
if is_valid(door, connect_door, sector, connect_sector, available_sectors):
|
||||||
|
# Apply connection and add the new region's doors to the available list
|
||||||
|
maybe_connect_two_way(world, door, connect_door, player)
|
||||||
|
reachable_doors.remove(door)
|
||||||
|
connect_sector.outstanding_doors.remove(connect_door)
|
||||||
|
if sector != connect_sector: # combine if not the same
|
||||||
available_sectors.remove(connect_sector)
|
available_sectors.remove(connect_sector)
|
||||||
current_sector.outstanding_doors.extend(connect_sector.outstanding_doors)
|
sector.outstanding_doors.extend(connect_sector.outstanding_doors)
|
||||||
current_sector.regions.extend(connect_sector.regions)
|
sector.regions.extend(connect_sector.regions)
|
||||||
break
|
if not door.blocked:
|
||||||
logger.info(' Not Linking %s to %s', door.name, connect_door.name)
|
connect_region = world.get_entrance(door.dest.name, player).parent_region
|
||||||
if len(compatibles) == 0: # time to try again
|
potential_new_doors, visited_regions = extend_reachable([connect_region], visited_regions, world, player)
|
||||||
current_sector.outstanding_doors.insert(0, door)
|
reachable_doors.extend(potential_new_doors)
|
||||||
if len(current_sector.outstanding_doors) <= 1:
|
break # skips else block below
|
||||||
raise Exception('Rejected last option due to dead end... infinite loop ensues')
|
logger.info(' Not Linking %s to %s', door.name, connect_door.name)
|
||||||
else:
|
if len(compatibles) == 0: # time to try again
|
||||||
# If there's no available region with a door, use an internal connection
|
sector.outstanding_doors.insert(0, door)
|
||||||
# todo: find all possibles for this door first
|
if len(reachable_doors) <= 1:
|
||||||
connect_door = find_compatible_door_in_list_old(world, door, current_sector.outstanding_doors, player)
|
raise Exception('Rejected last option due to dead end... infinite loop ensues')
|
||||||
if connect_door is not None:
|
else:
|
||||||
logger.info(' Adding loop via %s', connect_door.name)
|
# If there's no available region with a door, use an internal connection
|
||||||
# Check if valid
|
# todo: find all possibles for this door first
|
||||||
if is_loop_valid(door, connect_door, current_sector, len(available_sectors) == 0):
|
connect_door = find_compatible_door_in_list_old(world, door, reachable_doors, player)
|
||||||
maybe_connect_two_way(world, door, connect_door, player)
|
if connect_door is not None:
|
||||||
current_sector.outstanding_doors.remove(connect_door)
|
logger.info(' Adding loop via %s', connect_door.name)
|
||||||
else:
|
# Check if valid
|
||||||
logger.info(' Not Linking %s to %s', door.name, connect_door.name)
|
if is_loop_valid(door, connect_door, sector, len(available_sectors) == 1):
|
||||||
current_sector.outstanding_doors.insert(0, door)
|
maybe_connect_two_way(world, door, connect_door, player)
|
||||||
if len(current_sector.outstanding_doors) <= 2:
|
reachable_doors.remove(door)
|
||||||
raise Exception('Rejected last option due to likely improper loops...')
|
reachable_doors.remove(connect_door)
|
||||||
|
connect_sector = find_sector_for_door(connect_door, available_sectors)
|
||||||
|
connect_sector.outstanding_doors.remove(connect_door)
|
||||||
|
if sector != connect_sector: # combine if not the same
|
||||||
|
available_sectors.remove(connect_sector)
|
||||||
|
sector.outstanding_doors.extend(connect_sector.outstanding_doors)
|
||||||
|
sector.regions.extend(connect_sector.regions)
|
||||||
else:
|
else:
|
||||||
raise Exception('Something has gone terribly wrong')
|
logger.info(' Not Linking %s to %s', door.name, connect_door.name)
|
||||||
|
sector.outstanding_doors.insert(0, door)
|
||||||
|
if len(reachable_doors) <= 2:
|
||||||
|
raise Exception('Rejected last option due to likely improper loops...')
|
||||||
|
else:
|
||||||
|
raise Exception('Something has gone terribly wrong')
|
||||||
# Check that we used everything, we failed otherwise
|
# Check that we used everything, we failed otherwise
|
||||||
if len(available_sectors) > 0 or len(current_sector.outstanding_doors) > 0:
|
if len(available_sectors) != 1:
|
||||||
logger.warning('Failed to add all regions/doors to dungeon, generation will likely fail.')
|
logger.warning('Failed to add all regions/doors to dungeon, generation will likely fail.')
|
||||||
|
|
||||||
|
|
||||||
def find_all_compatible_door_in_sectors_ex(door, sectors):
|
def extend_reachable(search_regions, visited_regions, world, player):
|
||||||
|
region_list = list(search_regions)
|
||||||
|
visited_regions = visited_regions
|
||||||
|
reachable_doors = []
|
||||||
|
while len(region_list) > 0:
|
||||||
|
region = region_list.pop()
|
||||||
|
visited_regions.append(region)
|
||||||
|
for ext in region.exits:
|
||||||
|
if ext.connected_region is not None:
|
||||||
|
connect_region = ext.connected_region
|
||||||
|
if connect_region not in visited_regions and connect_region not in region_list:
|
||||||
|
region_list.append(connect_region)
|
||||||
|
else:
|
||||||
|
door = world.check_for_door(ext.name, player)
|
||||||
|
if door is not None and door.dest is None: # make sure it isn't a weird blocked door
|
||||||
|
reachable_doors.append(door)
|
||||||
|
return reachable_doors, visited_regions
|
||||||
|
|
||||||
|
|
||||||
|
def find_sector_for_door(door, sectors):
|
||||||
|
for sector in sectors:
|
||||||
|
if door in sector.outstanding_doors:
|
||||||
|
return sector
|
||||||
|
return None
|
||||||
|
|
||||||
|
|
||||||
|
def find_all_compatible_door_in_sectors_ex(door, sectors, reachable_doors):
|
||||||
result = []
|
result = []
|
||||||
for sector in sectors:
|
for sector in sectors:
|
||||||
for proposed_door in sector.outstanding_doors:
|
for proposed_door in sector.outstanding_doors:
|
||||||
if doors_compatible_ignore_keys(door, proposed_door):
|
if doors_compatible_ignore_keys(door, proposed_door) and proposed_door not in reachable_doors:
|
||||||
result.append((sector, proposed_door))
|
result.append((sector, proposed_door))
|
||||||
return result
|
return result
|
||||||
|
|
||||||
@@ -603,8 +649,8 @@ def doors_compatible_ignore_keys(a, b):
|
|||||||
if a.type != b.type:
|
if a.type != b.type:
|
||||||
return False
|
return False
|
||||||
# todo: test spirals linking to each other
|
# todo: test spirals linking to each other
|
||||||
# if a.type == DoorType.SpiralStairs:
|
if a.type == DoorType.SpiralStairs:
|
||||||
# return True
|
return True
|
||||||
return a.direction == switch_dir(b.direction)
|
return a.direction == switch_dir(b.direction)
|
||||||
|
|
||||||
|
|
||||||
@@ -612,6 +658,8 @@ def doors_compatible_ignore_keys(a, b):
|
|||||||
def is_valid(door_a, door_b, sector_a, sector_b, available_sectors):
|
def is_valid(door_a, door_b, sector_a, sector_b, available_sectors):
|
||||||
if len(available_sectors) == 1:
|
if len(available_sectors) == 1:
|
||||||
return True
|
return True
|
||||||
|
if len(available_sectors) <= 2 and sector_a != sector_b:
|
||||||
|
return True
|
||||||
elif not are_there_outstanding_doors_of_type(door_a, door_b, sector_a, sector_b, available_sectors):
|
elif not are_there_outstanding_doors_of_type(door_a, door_b, sector_a, sector_b, available_sectors):
|
||||||
return False
|
return False
|
||||||
elif door_a.blocked and door_b.blocked: # I can't see this going well unless we are in loop generation...
|
elif door_a.blocked and door_b.blocked: # I can't see this going well unless we are in loop generation...
|
||||||
@@ -647,12 +695,12 @@ def are_there_outstanding_doors_of_type(door_a, door_b, sector_a, sector_b, avai
|
|||||||
if only_neutral_left:
|
if only_neutral_left:
|
||||||
hooks_left = False
|
hooks_left = False
|
||||||
for door in sector_a.outstanding_doors:
|
for door in sector_a.outstanding_doors:
|
||||||
if door != door_a and pol_idx[door.direction][0] == idx:
|
if door != door_a and door != door_b and pol_idx[door.direction][0] == idx:
|
||||||
hooks_left = True
|
hooks_left = True
|
||||||
break
|
break
|
||||||
if not hooks_left:
|
if not hooks_left:
|
||||||
for door in sector_b.outstanding_doors:
|
for door in sector_b.outstanding_doors:
|
||||||
if door != door_b and pol_idx[door.direction][0] == idx:
|
if door != door_b and door != door_a and pol_idx[door.direction][0] == idx:
|
||||||
hooks_left = True
|
hooks_left = True
|
||||||
break
|
break
|
||||||
return hooks_left
|
return hooks_left
|
||||||
@@ -683,11 +731,16 @@ spiral_staircases = [
|
|||||||
('Hera Startile Wide Up Stairs', 'Hera 4F Down Stairs'),
|
('Hera Startile Wide Up Stairs', 'Hera 4F Down Stairs'),
|
||||||
('Hera 4F Up Stairs', 'Hera 5F Down Stairs'),
|
('Hera 4F Up Stairs', 'Hera 5F Down Stairs'),
|
||||||
('Hera 5F Up Stairs', 'Hera Boss Down Stairs'),
|
('Hera 5F Up Stairs', 'Hera Boss Down Stairs'),
|
||||||
|
('Tower Room 03 Up Stairs', 'Tower Lone Statue Down Stairs'),
|
||||||
|
('Tower Dark Chargers Up Stairs', 'Tower Dual Statues Down Stairs'),
|
||||||
|
('Tower Dark Archers Up Stairs', 'Tower Red Spears Down Stairs'),
|
||||||
|
('Tower Pacifist Run Up Stairs','Tower Push Statue Down Stairs'),
|
||||||
]
|
]
|
||||||
|
|
||||||
straight_staircases = [
|
straight_staircases = [
|
||||||
('Hyrule Castle Lobby North Stairs', 'Hyrule Castle Throne Room South Stairs'),
|
('Hyrule Castle Lobby North Stairs', 'Hyrule Castle Throne Room South Stairs'),
|
||||||
('Sewers Rope Room North Stairs', 'Sewers Dark Cross South Stairs')
|
('Sewers Rope Room North Stairs', 'Sewers Dark Cross South Stairs'),
|
||||||
|
('Tower Catwalk North Stairs', 'Tower Antechamber South Stairs')
|
||||||
]
|
]
|
||||||
|
|
||||||
open_edges = [
|
open_edges = [
|
||||||
@@ -743,6 +796,17 @@ interior_doors = [
|
|||||||
('Hera Tridorm SE', 'Hera Torches NE'),
|
('Hera Tridorm SE', 'Hera Torches NE'),
|
||||||
('Hera Beetles WS', 'Hera Startile Corner ES'),
|
('Hera Beetles WS', 'Hera Startile Corner ES'),
|
||||||
('Hera Startile Corner NW', 'Hera Startile Wide SW'),
|
('Hera Startile Corner NW', 'Hera Startile Wide SW'),
|
||||||
|
('Tower Lobby NW', 'Tower Gold Knights SW'),
|
||||||
|
('Tower Gold Knights EN', 'Tower Room 03 WN'),
|
||||||
|
('Tower Lone Statue WN', 'Tower Dark Maze EN'),
|
||||||
|
('Tower Dark Maze ES', 'Tower Dark Chargers WS'),
|
||||||
|
('Tower Dual Statues WS', 'Tower Dark Pits ES'),
|
||||||
|
('Tower Dark Pits EN', 'Tower Dark Archers WS'),
|
||||||
|
('Tower Red Spears WN', 'Tower Red Guards EN'),
|
||||||
|
('Tower Red Guards SW', 'Tower Circle of Pots NW'),
|
||||||
|
('Tower Circle of Pots WS', 'Tower Pacifist Run ES'),
|
||||||
|
('Tower Push Statue WS', 'Tower Catwalk ES'),
|
||||||
|
('Tower Antechamber NW', 'Tower Altar SW'),
|
||||||
]
|
]
|
||||||
|
|
||||||
key_doors = [
|
key_doors = [
|
||||||
@@ -795,7 +859,8 @@ default_door_connections = [
|
|||||||
default_one_way_connections = [
|
default_one_way_connections = [
|
||||||
('Sewers Pull Switch S', 'Sanctuary N'),
|
('Sewers Pull Switch S', 'Sanctuary N'),
|
||||||
('Eastern Eyegores NE', 'Eastern Boss SE'),
|
('Eastern Eyegores NE', 'Eastern Boss SE'),
|
||||||
('Desert Wall Slide NW', 'Desert Boss SW')
|
('Desert Wall Slide NW', 'Desert Boss SW'),
|
||||||
|
('Tower Altar NW', 'Tower Agahnim 1 SW')
|
||||||
]
|
]
|
||||||
|
|
||||||
# todo: these path rules are more complicated I think...
|
# todo: these path rules are more complicated I think...
|
||||||
@@ -827,7 +892,8 @@ default_dungeon_sets = [
|
|||||||
'Hyrule Dungeon Cellblock'],
|
'Hyrule Dungeon Cellblock'],
|
||||||
['Eastern Lobby', 'Eastern Boss'],
|
['Eastern Lobby', 'Eastern Boss'],
|
||||||
['Desert Back Lobby', 'Desert Boss', 'Desert Main Lobby', 'Desert West Lobby', 'Desert East Lobby'],
|
['Desert Back Lobby', 'Desert Boss', 'Desert Main Lobby', 'Desert West Lobby', 'Desert East Lobby'],
|
||||||
['Hera Lobby', 'Hera Boss']
|
['Hera Lobby', 'Hera Boss'],
|
||||||
|
['Tower Lobby', 'Tower Agahnim 1']
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
@@ -835,3 +901,19 @@ desert_default_entrance_sets = [
|
|||||||
['Desert Back Lobby'],
|
['Desert Back Lobby'],
|
||||||
['Desert Main Lobby', 'Desert West Lobby', 'Desert East Lobby']
|
['Desert Main Lobby', 'Desert West Lobby', 'Desert East Lobby']
|
||||||
]
|
]
|
||||||
|
|
||||||
|
# 'Skull': ['Skull 1 Lobby', 'Skull 2 Mummy Lobby', 'Skull 2 Key Lobby', 'Skull 3 Lobby'],
|
||||||
|
|
||||||
|
entrance_sets = [
|
||||||
|
['Hyrule Castle Lobby', 'Hyrule Castle West Lobby', 'Hyrule Castle East Lobby', 'Sewers Secret Room'],
|
||||||
|
['Eastern Lobby'],
|
||||||
|
['Hera Lobby'],
|
||||||
|
['Tower Lobby'],
|
||||||
|
# ['PoD Lobby'],
|
||||||
|
# ['Swamp Lobby'],
|
||||||
|
# ['TT Lobby'],
|
||||||
|
# ['Ice Lobby'],
|
||||||
|
# ['Mire Lobby'],
|
||||||
|
# ['TR Main Lobby', 'TR Eye Trap', 'TR Big Chest', 'TR Laser Bridge'],
|
||||||
|
# ['GT Lobby']
|
||||||
|
]
|
||||||
|
|||||||
36
Doors.py
36
Doors.py
@@ -213,6 +213,42 @@ def create_doors(world, player):
|
|||||||
create_spiral_stairs(player, 'Hera Boss Down Stairs', DoorType.SpiralStairs, Direction.Down, 0x07, 0, HTH, S, 0x61, 0xb0),
|
create_spiral_stairs(player, 'Hera Boss Down Stairs', DoorType.SpiralStairs, Direction.Down, 0x07, 0, HTH, S, 0x61, 0xb0),
|
||||||
create_door(player, 'Hera Boss Outer Hole', DoorType.Hole),
|
create_door(player, 'Hera Boss Outer Hole', DoorType.Hole),
|
||||||
create_door(player, 'Hera Boss Inner Hole', DoorType.Hole),
|
create_door(player, 'Hera Boss Inner Hole', DoorType.Hole),
|
||||||
|
|
||||||
|
# Castle Tower
|
||||||
|
create_dir_door(player, 'Tower Lobby NW', DoorType.Interior, Direction.North, 0xe0, Left, High),
|
||||||
|
create_dir_door(player, 'Tower Gold Knights SW', DoorType.Interior, Direction.South, 0xe0, Left, High),
|
||||||
|
create_dir_door(player, 'Tower Gold Knights EN', DoorType.Interior, Direction.East, 0xe0, Top, High),
|
||||||
|
create_dir_door(player, 'Tower Room 03 WN', DoorType.Interior, Direction.West, 0xe0, Bot, High),
|
||||||
|
small_key(create_spiral_stairs(player, 'Tower Room 03 Up Stairs', DoorType.SpiralStairs, Direction.Up, 0xe0, 0, HTH, S, 0x1a, 0x6c)),
|
||||||
|
create_spiral_stairs(player, 'Tower Lone Statue Down Stairs', DoorType.SpiralStairs, Direction.Down, 0xd0, 0, HTH, S, 0x11, 0x80),
|
||||||
|
create_dir_door(player, 'Tower Lone Statue WN', DoorType.Interior, Direction.West, 0xd0, Top, High),
|
||||||
|
create_dir_door(player, 'Tower Dark Maze EN', DoorType.Interior, Direction.East, 0xd0, Top, High),
|
||||||
|
small_key(create_dir_door(player, 'Tower Dark Maze ES', DoorType.Interior, Direction.East, 0xd0, Bot, High)),
|
||||||
|
small_key(create_dir_door(player, 'Tower Dark Chargers WS', DoorType.Interior, Direction.West, 0xd0, Bot, High)),
|
||||||
|
create_spiral_stairs(player, 'Tower Dark Chargers Up Stairs', DoorType.SpiralStairs, Direction.Up, 0xd0, 0, HTH, X, 0x1b, 0x8c),
|
||||||
|
create_spiral_stairs(player, 'Tower Dual Statues Down Stairs', DoorType.SpiralStairs, Direction.Down, 0xc0, 0, HTH, X, 0x12, 0xa0),
|
||||||
|
create_dir_door(player, 'Tower Dual Statues WS', DoorType.Interior, Direction.West, 0xc0, Bot, High),
|
||||||
|
create_dir_door(player, 'Tower Dark Pits ES', DoorType.Interior, Direction.East, 0xc0, Bot, High),
|
||||||
|
create_dir_door(player, 'Tower Dark Pits EN', DoorType.Interior, Direction.East, 0xc0, Top, High),
|
||||||
|
create_dir_door(player, 'Tower Dark Archers WS', DoorType.Interior, Direction.West, 0xc0, Top, High),
|
||||||
|
small_key(create_spiral_stairs(player, 'Tower Dark Archers Up Stairs', DoorType.SpiralStairs, Direction.Up, 0xc0, 0, HTH, S, 0x1b, 0x6c)),
|
||||||
|
create_spiral_stairs(player, 'Tower Red Spears Down Stairs', DoorType.SpiralStairs, Direction.Down, 0xb0, 0, HTH, S, 0x12, 0x80),
|
||||||
|
create_dir_door(player, 'Tower Red Spears WN', DoorType.Interior, Direction.West, 0xb0, Top, High),
|
||||||
|
create_dir_door(player, 'Tower Red Guards EN', DoorType.Interior, Direction.East, 0xb0, Top, High),
|
||||||
|
create_dir_door(player, 'Tower Red Guards SW', DoorType.Interior, Direction.South, 0xb0, Left, High),
|
||||||
|
create_dir_door(player, 'Tower Circle of Pots NW', DoorType.Interior, Direction.North, 0xb0, Left, High),
|
||||||
|
small_key(create_dir_door(player, 'Tower Circle of Pots WS', DoorType.Interior, Direction.West, 0xb0, Bot, High)),
|
||||||
|
small_key(create_dir_door(player, 'Tower Pacifist Run ES', DoorType.Interior, Direction.East, 0xb0, Bot, High)),
|
||||||
|
create_spiral_stairs(player, 'Tower Pacifist Run Up Stairs', DoorType.SpiralStairs, Direction.Up, 0xb0, 0, LTH, S, 0x33, 0x8c),
|
||||||
|
create_spiral_stairs(player, 'Tower Push Statue Down Stairs', DoorType.SpiralStairs, Direction.Down, 0x40, 0, HTL, X, 0x12, 0xa0),
|
||||||
|
create_dir_door(player, 'Tower Push Statue WS', DoorType.Interior, Direction.West, 0x40, Bot, Low),
|
||||||
|
create_dir_door(player, 'Tower Catwalk ES', DoorType.Interior, Direction.East, 0x40, Bot, Low),
|
||||||
|
create_dir_door(player, 'Tower Catwalk North Stairs', DoorType.StraightStairs, Direction.North, 0x40, Left, High),
|
||||||
|
create_dir_door(player, 'Tower Antechamber South Stairs', DoorType.StraightStairs, Direction.South, 0x30, Left, High),
|
||||||
|
create_dir_door(player, 'Tower Antechamber NW', DoorType.Interior, Direction.North, 0x30, Left, High),
|
||||||
|
create_dir_door(player, 'Tower Altar SW', DoorType.Interior, Direction.South, 0x30, Left, High),
|
||||||
|
create_dir_door(player, 'Tower Altar NW', DoorType.Normal, Direction.North, 0x30, Left, High),
|
||||||
|
trap(blocked(create_dir_door(player, 'Tower Agahnim 1 SW', DoorType.Normal, Direction.South, 0x20, Left, High)), 0x2),
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
25
Dungeons.py
25
Dungeons.py
@@ -30,7 +30,7 @@ def create_dungeons(world, player):
|
|||||||
TR = make_dungeon('Turtle Rock', 'Trinexx', ['Turtle Rock (Entrance)', 'Turtle Rock (First Section)', 'Turtle Rock (Chain Chomp Room)', 'Turtle Rock (Second Section)', 'Turtle Rock (Big Chest)', 'Turtle Rock (Crystaroller Room)', 'Turtle Rock (Dark Room)', 'Turtle Rock (Eye Bridge)', 'Turtle Rock (Trinexx)'], ItemFactory('Big Key (Turtle Rock)', player), ItemFactory(['Small Key (Turtle Rock)'] * 4, player), ItemFactory(['Map (Turtle Rock)', 'Compass (Turtle Rock)'], player))
|
TR = make_dungeon('Turtle Rock', 'Trinexx', ['Turtle Rock (Entrance)', 'Turtle Rock (First Section)', 'Turtle Rock (Chain Chomp Room)', 'Turtle Rock (Second Section)', 'Turtle Rock (Big Chest)', 'Turtle Rock (Crystaroller Room)', 'Turtle Rock (Dark Room)', 'Turtle Rock (Eye Bridge)', 'Turtle Rock (Trinexx)'], ItemFactory('Big Key (Turtle Rock)', player), ItemFactory(['Small Key (Turtle Rock)'] * 4, player), ItemFactory(['Map (Turtle Rock)', 'Compass (Turtle Rock)'], player))
|
||||||
|
|
||||||
if world.mode != 'inverted':
|
if world.mode != 'inverted':
|
||||||
AT = make_dungeon('Agahnims Tower', 'Agahnim', ['Agahnims Tower', 'Agahnim 1'], None, ItemFactory(['Small Key (Agahnims Tower)'] * 2, player), [])
|
AT = make_dungeon('Agahnims Tower', 'Agahnim', tower_regions, None, ItemFactory(['Small Key (Agahnims Tower)'] * 2, player), [])
|
||||||
GT = make_dungeon('Ganons Tower', 'Agahnim2', ['Ganons Tower (Entrance)', 'Ganons Tower (Tile Room)', 'Ganons Tower (Compass Room)', 'Ganons Tower (Hookshot Room)', 'Ganons Tower (Map Room)', 'Ganons Tower (Firesnake Room)', 'Ganons Tower (Teleport Room)', 'Ganons Tower (Bottom)', 'Ganons Tower (Top)', 'Ganons Tower (Before Moldorm)', 'Ganons Tower (Moldorm)', 'Agahnim 2'], ItemFactory('Big Key (Ganons Tower)', player), ItemFactory(['Small Key (Ganons Tower)'] * 4, player), ItemFactory(['Map (Ganons Tower)', 'Compass (Ganons Tower)'], player))
|
GT = make_dungeon('Ganons Tower', 'Agahnim2', ['Ganons Tower (Entrance)', 'Ganons Tower (Tile Room)', 'Ganons Tower (Compass Room)', 'Ganons Tower (Hookshot Room)', 'Ganons Tower (Map Room)', 'Ganons Tower (Firesnake Room)', 'Ganons Tower (Teleport Room)', 'Ganons Tower (Bottom)', 'Ganons Tower (Top)', 'Ganons Tower (Before Moldorm)', 'Ganons Tower (Moldorm)', 'Agahnim 2'], ItemFactory('Big Key (Ganons Tower)', player), ItemFactory(['Small Key (Ganons Tower)'] * 4, player), ItemFactory(['Map (Ganons Tower)', 'Compass (Ganons Tower)'], player))
|
||||||
else:
|
else:
|
||||||
AT = make_dungeon('Inverted Agahnims Tower', 'Agahnim', ['Inverted Agahnims Tower', 'Agahnim 1'], None, ItemFactory(['Small Key (Agahnims Tower)'] * 2, player), [])
|
AT = make_dungeon('Inverted Agahnims Tower', 'Agahnim', ['Inverted Agahnims Tower', 'Agahnim 1'], None, ItemFactory(['Small Key (Agahnims Tower)'] * 2, player), [])
|
||||||
@@ -197,3 +197,26 @@ hera_regions = [
|
|||||||
'Hera Startile Corner', 'Hera Startile Wide', 'Hera 4F', 'Hera Big Chest Landing', 'Hera 5F',
|
'Hera Startile Corner', 'Hera Startile Wide', 'Hera 4F', 'Hera Big Chest Landing', 'Hera 5F',
|
||||||
'Hera Fairies', 'Hera Boss'
|
'Hera Fairies', 'Hera Boss'
|
||||||
]
|
]
|
||||||
|
|
||||||
|
tower_regions = [
|
||||||
|
'Tower Lobby', 'Tower Gold Knights', 'Tower Room 03', 'Tower Lone Statue', 'Tower Dark Maze', 'Tower Dark Chargers',
|
||||||
|
'Tower Dual Statues', 'Tower Dark Pits', 'Tower Dark Archers', 'Tower Red Spears', 'Tower Red Guards',
|
||||||
|
'Tower Circle of Pots', 'Tower Pacifist Run', 'Tower Push Statue', 'Tower Catwalk', 'Tower Antechamber',
|
||||||
|
'Tower Altar', 'Tower Agahnim 1'
|
||||||
|
]
|
||||||
|
|
||||||
|
dungeon_regions = {
|
||||||
|
'Hyrule Castle': hyrule_castle_regions,
|
||||||
|
'Eastern': eastern_regions,
|
||||||
|
'Desert': desert_regions,
|
||||||
|
'Hera': hera_regions,
|
||||||
|
'Tower': tower_regions,
|
||||||
|
# 'PoD':
|
||||||
|
# 'Swamp':
|
||||||
|
# 'Skull':
|
||||||
|
# 'TT':
|
||||||
|
# 'Ice':
|
||||||
|
# 'Mire':
|
||||||
|
# 'TR':
|
||||||
|
# 'GT':
|
||||||
|
}
|
||||||
|
|||||||
@@ -2848,7 +2848,6 @@ mandatory_connections = [('Lake Hylia Central Island Pier', 'Lake Hylia Central
|
|||||||
('Hyrule Castle Ledge Courtyard Drop', 'Hyrule Castle Courtyard'),
|
('Hyrule Castle Ledge Courtyard Drop', 'Hyrule Castle Courtyard'),
|
||||||
('Hyrule Castle Main Gate', 'Hyrule Castle Courtyard'),
|
('Hyrule Castle Main Gate', 'Hyrule Castle Courtyard'),
|
||||||
('Sewer Drop', 'Sewers Secret Room'),
|
('Sewer Drop', 'Sewers Secret Room'),
|
||||||
('Agahnim 1', 'Agahnim 1'),
|
|
||||||
('Flute Spot 1', 'Death Mountain'),
|
('Flute Spot 1', 'Death Mountain'),
|
||||||
('Death Mountain Entrance Rock', 'Death Mountain Entrance'),
|
('Death Mountain Entrance Rock', 'Death Mountain Entrance'),
|
||||||
('Death Mountain Entrance Drop', 'Light World'),
|
('Death Mountain Entrance Drop', 'Light World'),
|
||||||
@@ -3527,7 +3526,7 @@ default_dungeon_connections = [('Desert Palace Entrance (South)', 'Desert Main L
|
|||||||
('Hyrule Castle Exit (South)', 'Light World'),
|
('Hyrule Castle Exit (South)', 'Light World'),
|
||||||
('Hyrule Castle Exit (West)', 'Hyrule Castle Ledge'),
|
('Hyrule Castle Exit (West)', 'Hyrule Castle Ledge'),
|
||||||
('Hyrule Castle Exit (East)', 'Hyrule Castle Ledge'),
|
('Hyrule Castle Exit (East)', 'Hyrule Castle Ledge'),
|
||||||
('Agahnims Tower', 'Agahnims Tower'),
|
('Agahnims Tower', 'Tower Lobby'),
|
||||||
('Agahnims Tower Exit', 'Hyrule Castle Ledge'),
|
('Agahnims Tower Exit', 'Hyrule Castle Ledge'),
|
||||||
|
|
||||||
('Thieves Town', 'Thieves Town (Entrance)'),
|
('Thieves Town', 'Thieves Town (Entrance)'),
|
||||||
|
|||||||
9
Gui.py
9
Gui.py
@@ -155,6 +155,14 @@ def guiMain(args=None):
|
|||||||
logicLabel = Label(logicFrame, text='Game logic')
|
logicLabel = Label(logicFrame, text='Game logic')
|
||||||
logicLabel.pack(side=LEFT)
|
logicLabel.pack(side=LEFT)
|
||||||
|
|
||||||
|
swordsFrame = Frame(drowDownFrame)
|
||||||
|
swordsVar = StringVar()
|
||||||
|
swordsVar.set('random')
|
||||||
|
swordsOptionMenu = OptionMenu(swordsFrame, swordsVar, 'random', 'assured', 'swordless', 'vanilla')
|
||||||
|
swordsOptionMenu.pack(side=RIGHT)
|
||||||
|
swordsLabel = Label(swordsFrame, text='Swords')
|
||||||
|
swordsLabel.pack(side=LEFT)
|
||||||
|
|
||||||
goalFrame = Frame(drowDownFrame)
|
goalFrame = Frame(drowDownFrame)
|
||||||
goalVar = StringVar()
|
goalVar = StringVar()
|
||||||
goalVar.set('ganon')
|
goalVar.set('ganon')
|
||||||
@@ -323,6 +331,7 @@ def guiMain(args=None):
|
|||||||
guiargs.count = int(countVar.get()) if countVar.get() != '1' else None
|
guiargs.count = int(countVar.get()) if countVar.get() != '1' else None
|
||||||
guiargs.mode = modeVar.get()
|
guiargs.mode = modeVar.get()
|
||||||
guiargs.logic = logicVar.get()
|
guiargs.logic = logicVar.get()
|
||||||
|
guiargs.swords = swordsVar.get()
|
||||||
guiargs.goal = goalVar.get()
|
guiargs.goal = goalVar.get()
|
||||||
guiargs.difficulty = difficultyVar.get()
|
guiargs.difficulty = difficultyVar.get()
|
||||||
guiargs.timer = timerVar.get()
|
guiargs.timer = timerVar.get()
|
||||||
|
|||||||
11
Main.py
11
Main.py
@@ -20,7 +20,7 @@ from Fill import distribute_items_cutoff, distribute_items_staleness, distribute
|
|||||||
from ItemList import generate_itempool, difficulties, fill_prizes
|
from ItemList import generate_itempool, difficulties, fill_prizes
|
||||||
from Utils import output_path
|
from Utils import output_path
|
||||||
|
|
||||||
__version__ = '0.6.3-pre'
|
__version__ = '0.0.1-pre'
|
||||||
|
|
||||||
def main(args, seed=None):
|
def main(args, seed=None):
|
||||||
start = time.clock()
|
start = time.clock()
|
||||||
@@ -40,7 +40,7 @@ def main(args, seed=None):
|
|||||||
|
|
||||||
world.rom_seeds = {player: random.randint(0, 999999999) for player in range(1, world.players + 1)}
|
world.rom_seeds = {player: random.randint(0, 999999999) for player in range(1, world.players + 1)}
|
||||||
|
|
||||||
logger.info('ALttP Entrance Randomizer Version %s - Seed: %s\n\n', __version__, world.seed)
|
logger.info('ALttP Door Randomizer Version %s - Seed: %s\n\n', __version__, world.seed)
|
||||||
|
|
||||||
world.difficulty_requirements = difficulties[world.difficulty]
|
world.difficulty_requirements = difficulties[world.difficulty]
|
||||||
|
|
||||||
@@ -83,6 +83,13 @@ def main(args, seed=None):
|
|||||||
for player in range(1, world.players + 1):
|
for player in range(1, world.players + 1):
|
||||||
set_rules(world, player)
|
set_rules(world, player)
|
||||||
|
|
||||||
|
# todo: remove this later. this is for debugging
|
||||||
|
for player in range(1, world.players + 1):
|
||||||
|
all_state = world.get_all_state(keys=True)
|
||||||
|
for bossregion in ['Eastern Boss', 'Desert Boss', 'Hera Boss', 'Tower Agahnim 1']:
|
||||||
|
if world.get_region(bossregion, player) not in all_state.reachable_regions[player]:
|
||||||
|
raise Exception(bossregion + ' missing from generation')
|
||||||
|
|
||||||
logger.info('Placing Dungeon Prizes.')
|
logger.info('Placing Dungeon Prizes.')
|
||||||
|
|
||||||
fill_prizes(world)
|
fill_prizes(world)
|
||||||
|
|||||||
25
Regions.py
25
Regions.py
@@ -99,8 +99,7 @@ def create_regions(world, player):
|
|||||||
create_lw_region(player, 'Hyrule Castle Courtyard', None, ['Hyrule Castle Secret Entrance Stairs', 'Hyrule Castle Entrance (South)']),
|
create_lw_region(player, 'Hyrule Castle Courtyard', None, ['Hyrule Castle Secret Entrance Stairs', 'Hyrule Castle Entrance (South)']),
|
||||||
create_lw_region(player, 'Hyrule Castle Ledge', None, ['Hyrule Castle Entrance (East)', 'Hyrule Castle Entrance (West)', 'Agahnims Tower', 'Hyrule Castle Ledge Courtyard Drop']),
|
create_lw_region(player, 'Hyrule Castle Ledge', None, ['Hyrule Castle Entrance (East)', 'Hyrule Castle Entrance (West)', 'Agahnims Tower', 'Hyrule Castle Ledge Courtyard Drop']),
|
||||||
create_dungeon_region(player, 'Sewer Drop', 'a drop\'s exit', None, ['Sewer Drop']), # This exists only to be referenced for access checks
|
create_dungeon_region(player, 'Sewer Drop', 'a drop\'s exit', None, ['Sewer Drop']), # This exists only to be referenced for access checks
|
||||||
create_dungeon_region(player, 'Agahnims Tower', 'Castle Tower', ['Castle Tower - Room 03', 'Castle Tower - Dark Maze'], ['Agahnim 1', 'Agahnims Tower Exit']),
|
|
||||||
create_dungeon_region(player, 'Agahnim 1', 'Castle Tower', ['Agahnim 1'], None),
|
|
||||||
create_cave_region(player, 'Old Man Cave', 'a connector', ['Old Man'], ['Old Man Cave Exit (East)', 'Old Man Cave Exit (West)']),
|
create_cave_region(player, 'Old Man Cave', 'a connector', ['Old Man'], ['Old Man Cave Exit (East)', 'Old Man Cave Exit (West)']),
|
||||||
create_cave_region(player, 'Old Man House', 'a connector', None, ['Old Man House Exit (Bottom)', 'Old Man House Front to Back']),
|
create_cave_region(player, 'Old Man House', 'a connector', None, ['Old Man House Exit (Bottom)', 'Old Man House Front to Back']),
|
||||||
create_cave_region(player, 'Old Man House Back', 'a connector', None, ['Old Man House Exit (Top)', 'Old Man House Back to Front']),
|
create_cave_region(player, 'Old Man House Back', 'a connector', None, ['Old Man House Exit (Top)', 'Old Man House Back to Front']),
|
||||||
@@ -374,6 +373,24 @@ def create_regions(world, player):
|
|||||||
create_dungeon_region(player, 'Hera Boss', 'Tower of Hera', ['Tower of Hera - Boss', 'Tower of Hera - Prize'], ['Hera Boss Down Stairs', 'Hera Boss Outer Hole', 'Hera Boss Inner Hole']),
|
create_dungeon_region(player, 'Hera Boss', 'Tower of Hera', ['Tower of Hera - Boss', 'Tower of Hera - Prize'], ['Hera Boss Down Stairs', 'Hera Boss Outer Hole', 'Hera Boss Inner Hole']),
|
||||||
|
|
||||||
# AgaTower
|
# AgaTower
|
||||||
|
create_dungeon_region(player, 'Tower Lobby', 'Castle Tower', None, ['Tower Lobby NW', 'Agahnims Tower Exit']),
|
||||||
|
create_dungeon_region(player, 'Tower Gold Knights', 'Castle Tower', None, ['Tower Gold Knights SW', 'Tower Gold Knights EN']),
|
||||||
|
create_dungeon_region(player, 'Tower Room 03', 'Castle Tower', ['Castle Tower - Room 03'], ['Tower Room 03 WN', 'Tower Room 03 Up Stairs']),
|
||||||
|
create_dungeon_region(player, 'Tower Lone Statue', 'Castle Tower', None, ['Tower Lone Statue Down Stairs', 'Tower Lone Statue WN']),
|
||||||
|
create_dungeon_region(player, 'Tower Dark Maze', 'Castle Tower', ['Castle Tower - Dark Maze'], ['Tower Dark Maze EN', 'Tower Dark Maze ES']),
|
||||||
|
create_dungeon_region(player, 'Tower Dark Chargers', 'Castle Tower', None, ['Tower Dark Chargers WS', 'Tower Dark Chargers Up Stairs']),
|
||||||
|
create_dungeon_region(player, 'Tower Dual Statues', 'Castle Tower', None, ['Tower Dual Statues Down Stairs', 'Tower Dual Statues WS']),
|
||||||
|
create_dungeon_region(player, 'Tower Dark Pits', 'Castle Tower', None, ['Tower Dark Pits ES', 'Tower Dark Pits EN']),
|
||||||
|
create_dungeon_region(player, 'Tower Dark Archers', 'Castle Tower', ['Castle Tower - Dark Archer Key Drop'], ['Tower Dark Archers WS', 'Tower Dark Archers Up Stairs']),
|
||||||
|
create_dungeon_region(player, 'Tower Red Spears', 'Castle Tower', None, ['Tower Red Spears Down Stairs', 'Tower Red Spears WN']),
|
||||||
|
create_dungeon_region(player, 'Tower Red Guards', 'Castle Tower', None, ['Tower Red Guards EN', 'Tower Red Guards SW']),
|
||||||
|
create_dungeon_region(player, 'Tower Circle of Pots', 'Castle Tower', ['Castle Tower - Circle of Pots Key Drop'], ['Tower Circle of Pots NW', 'Tower Circle of Pots WS']),
|
||||||
|
create_dungeon_region(player, 'Tower Pacifist Run', 'Castle Tower', None, ['Tower Pacifist Run ES', 'Tower Pacifist Run Up Stairs']),
|
||||||
|
create_dungeon_region(player, 'Tower Push Statue', 'Castle Tower', None, ['Tower Push Statue Down Stairs', 'Tower Push Statue WS']),
|
||||||
|
create_dungeon_region(player, 'Tower Catwalk', 'Castle Tower', None, ['Tower Catwalk ES', 'Tower Catwalk North Stairs']),
|
||||||
|
create_dungeon_region(player, 'Tower Antechamber', 'Castle Tower', None, ['Tower Antechamber South Stairs', 'Tower Antechamber NW']),
|
||||||
|
create_dungeon_region(player, 'Tower Altar', 'Castle Tower', None, ['Tower Altar SW', 'Tower Altar NW']),
|
||||||
|
create_dungeon_region(player, 'Tower Agahnim 1', 'Castle Tower', ['Agahnim 1'], ['Tower Agahnim 1 SW']),
|
||||||
|
|
||||||
# pod
|
# pod
|
||||||
# tt
|
# tt
|
||||||
@@ -383,8 +400,6 @@ def create_regions(world, player):
|
|||||||
# tr
|
# tr
|
||||||
# gt
|
# gt
|
||||||
# sw
|
# sw
|
||||||
|
|
||||||
|
|
||||||
]
|
]
|
||||||
|
|
||||||
for region_name, (room_id, shopkeeper, replaceable) in shop_table.items():
|
for region_name, (room_id, shopkeeper, replaceable) in shop_table.items():
|
||||||
@@ -504,6 +519,8 @@ key_only_locations = {
|
|||||||
'Desert Palace - Desert Tiles 1 Pot Key': 'Small Key (Desert Palace)',
|
'Desert Palace - Desert Tiles 1 Pot Key': 'Small Key (Desert Palace)',
|
||||||
'Desert Palace - Beamos Hall Pot Key': 'Small Key (Desert Palace)',
|
'Desert Palace - Beamos Hall Pot Key': 'Small Key (Desert Palace)',
|
||||||
'Desert Palace - Desert Tiles 2 Pot Key': 'Small Key (Desert Palace)',
|
'Desert Palace - Desert Tiles 2 Pot Key': 'Small Key (Desert Palace)',
|
||||||
|
'Castle Tower - Dark Archer Key Drop': 'Small Key (Agahnims Tower)',
|
||||||
|
'Castle Tower - Circle of Pots Key Drop': 'Small Key (Agahnims Tower)',
|
||||||
}
|
}
|
||||||
|
|
||||||
location_table = {'Mushroom': (0x180013, False, 'in the woods'),
|
location_table = {'Mushroom': (0x180013, False, 'in the woods'),
|
||||||
|
|||||||
2
Rom.py
2
Rom.py
@@ -18,7 +18,7 @@ from EntranceShuffle import door_addresses
|
|||||||
|
|
||||||
|
|
||||||
JAP10HASH = '03a63945398191337e896e5771f77173'
|
JAP10HASH = '03a63945398191337e896e5771f77173'
|
||||||
RANDOMIZERBASEHASH = '1cd7e88cb91720b52962a95662679c49'
|
RANDOMIZERBASEHASH = '760a7c62303ab662427661e58ab74a2d'
|
||||||
|
|
||||||
|
|
||||||
class JsonRom(object):
|
class JsonRom(object):
|
||||||
|
|||||||
13
Rules.py
13
Rules.py
@@ -171,7 +171,7 @@ def global_rules(world, player):
|
|||||||
set_rule(world.get_location('Master Sword Pedestal', player), lambda state: state.has('Red Pendant', player) and state.has('Blue Pendant', player) and state.has('Green Pendant', player))
|
set_rule(world.get_location('Master Sword Pedestal', player), lambda state: state.has('Red Pendant', player) and state.has('Blue Pendant', player) and state.has('Green Pendant', player))
|
||||||
set_rule(world.get_location('Sahasrahla', player), lambda state: state.has('Green Pendant', player))
|
set_rule(world.get_location('Sahasrahla', player), lambda state: state.has('Green Pendant', player))
|
||||||
set_rule(world.get_entrance('Agahnims Tower', player), lambda state: state.has('Cape', player) or state.has_beam_sword(player) or state.has('Beat Agahnim 1', player)) # barrier gets removed after killing agahnim, relevant for entrance shuffle
|
set_rule(world.get_entrance('Agahnims Tower', player), lambda state: state.has('Cape', player) or state.has_beam_sword(player) or state.has('Beat Agahnim 1', player)) # barrier gets removed after killing agahnim, relevant for entrance shuffle
|
||||||
set_rule(world.get_entrance('Agahnim 1', player), lambda state: state.has_sword(player) and state.has_key('Small Key (Agahnims Tower)', player, 2))
|
# set_rule(world.get_entrance('Agahnim 1', player), lambda state: state.has_sword(player) and state.has_key('Small Key (Agahnims Tower)', player, 2))
|
||||||
set_defeat_dungeon_boss_rule(world.get_location('Agahnim 1', player))
|
set_defeat_dungeon_boss_rule(world.get_location('Agahnim 1', player))
|
||||||
set_rule(world.get_location('Castle Tower - Dark Maze', player), lambda state: state.has_key('Small Key (Agahnims Tower)', player))
|
set_rule(world.get_location('Castle Tower - Dark Maze', player), lambda state: state.has_key('Small Key (Agahnims Tower)', player))
|
||||||
set_rule(world.get_entrance('Top of Pyramid', player), lambda state: state.has('Beat Agahnim 1', player))
|
set_rule(world.get_entrance('Top of Pyramid', player), lambda state: state.has('Beat Agahnim 1', player))
|
||||||
@@ -309,6 +309,8 @@ def global_rules(world, player):
|
|||||||
set_rule(world.get_location('Eastern Palace - Boss', player), lambda state: world.get_location('Eastern Palace - Boss', player).parent_region.dungeon.boss.can_defeat(state))
|
set_rule(world.get_location('Eastern Palace - Boss', player), lambda state: world.get_location('Eastern Palace - Boss', player).parent_region.dungeon.boss.can_defeat(state))
|
||||||
set_rule(world.get_location('Eastern Palace - Prize', player), lambda state: world.get_location('Eastern Palace - Prize', player).parent_region.dungeon.boss.can_defeat(state))
|
set_rule(world.get_location('Eastern Palace - Prize', player), lambda state: world.get_location('Eastern Palace - Prize', player).parent_region.dungeon.boss.can_defeat(state))
|
||||||
|
|
||||||
|
set_rule(world.get_entrance('Tower Altar NW', player), lambda state: state.has_sword(player))
|
||||||
|
|
||||||
# End of door rando rules.
|
# End of door rando rules.
|
||||||
|
|
||||||
# set_rule(world.get_entrance('Sewers Door', player), lambda state: state.has_key('Small Key (Escape)', player))
|
# set_rule(world.get_entrance('Sewers Door', player), lambda state: state.has_key('Small Key (Escape)', player))
|
||||||
@@ -950,10 +952,11 @@ def no_glitches_rules(world, player):
|
|||||||
add_conditional_lamp('Palace of Darkness Maze Door', 'Palace of Darkness (Entrance)', 'Entrance')
|
add_conditional_lamp('Palace of Darkness Maze Door', 'Palace of Darkness (Entrance)', 'Entrance')
|
||||||
add_conditional_lamp('Palace of Darkness - Dark Basement - Left', 'Palace of Darkness (Entrance)', 'Location')
|
add_conditional_lamp('Palace of Darkness - Dark Basement - Left', 'Palace of Darkness (Entrance)', 'Location')
|
||||||
add_conditional_lamp('Palace of Darkness - Dark Basement - Right', 'Palace of Darkness (Entrance)', 'Location')
|
add_conditional_lamp('Palace of Darkness - Dark Basement - Right', 'Palace of Darkness (Entrance)', 'Location')
|
||||||
if world.mode != 'inverted':
|
# todo: more lamp
|
||||||
add_conditional_lamp('Agahnim 1', 'Agahnims Tower', 'Entrance')
|
# if :
|
||||||
add_conditional_lamp('Castle Tower - Dark Maze', 'Agahnims Tower', 'Location')
|
# add_conditional_lamp('Agahnim 1', 'Agahnims Tower', 'Entrance')
|
||||||
else:
|
# add_conditional_lamp('Castle Tower - Dark Maze', 'Agahnims Tower', 'Location')
|
||||||
|
if world.mode == 'inverted':
|
||||||
add_conditional_lamp('Agahnim 1', 'Inverted Agahnims Tower', 'Entrance')
|
add_conditional_lamp('Agahnim 1', 'Inverted Agahnims Tower', 'Entrance')
|
||||||
add_conditional_lamp('Castle Tower - Dark Maze', 'Inverted Agahnims Tower', 'Location')
|
add_conditional_lamp('Castle Tower - Dark Maze', 'Inverted Agahnims Tower', 'Location')
|
||||||
add_conditional_lamp('Old Man', 'Old Man Cave', 'Location')
|
add_conditional_lamp('Old Man', 'Old Man Cave', 'Location')
|
||||||
|
|||||||
@@ -15,5 +15,3 @@ dw $3882, $3660, $1e81
|
|||||||
org $1fd974 ;(PC: 0fd974) TT Bossway 0xbc
|
org $1fd974 ;(PC: 0fd974) TT Bossway 0xbc
|
||||||
dw $1c82, $0081
|
dw $1c82, $0081
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -7,7 +7,9 @@ RecordStairType: {
|
|||||||
|
|
||||||
SpiralWarp: {
|
SpiralWarp: {
|
||||||
lda $040c : cmp.b #$ff : beq .abort ; abort if not in dungeon
|
lda $040c : cmp.b #$ff : beq .abort ; abort if not in dungeon
|
||||||
cmp #$06 : bcs .abort ; abort if not supported yet -- todo: this needs to be altered/removed as more dungeons are implemented
|
cmp #$14 : beq .check ; hera is okay
|
||||||
|
cmp #$0A : bcs .abort ; abort if not supported yet -- todo: this needs to be altered/removed as more dungeons are implemented
|
||||||
|
.check
|
||||||
lda $045e : cmp #$5e : beq .gtg ; abort if not spiral - intended room is in A!
|
lda $045e : cmp #$5e : beq .gtg ; abort if not spiral - intended room is in A!
|
||||||
cmp #$5f : beq .gtg
|
cmp #$5f : beq .gtg
|
||||||
.abort
|
.abort
|
||||||
|
|||||||
File diff suppressed because one or more lines are too long
Reference in New Issue
Block a user