Incremental improvements to algorithm.
Can get stuck in loop because it ran into a dead end only option early, not sure how to avoid that. Also, some landings are considered outstanding doors, that shouldn't happen.
This commit is contained in:
@@ -900,60 +900,55 @@ 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:
|
||||||
|
random.shuffle(sector.outstanding_doors)
|
||||||
|
|
||||||
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_sectors) > 0:
|
while len(available_sectors) > 0:
|
||||||
# Pick a random region and make its doors the open set
|
# Pick a random region and make its doors the open set
|
||||||
sector = available_sectors.pop()
|
sector = available_sectors.pop()
|
||||||
current_sector = sector
|
current_sector = sector
|
||||||
available_doors.extend(sector.outstanding_doors)
|
|
||||||
|
|
||||||
# Loop until all available doors are used
|
# Loop until all available doors are used
|
||||||
while len(available_doors) > 0:
|
while len(current_sector.outstanding_doors) > 0:
|
||||||
# Pick a random available door to connect
|
# Pick a random available door to connect
|
||||||
random.shuffle(available_doors)
|
random.shuffle(current_sector.outstanding_doors)
|
||||||
door = available_doors.pop()
|
door = current_sector.outstanding_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
|
||||||
connect_sector, connect_door = find_compatible_door_in_sectors_ex(world, door, available_sectors, player)
|
connect_sector, connect_door = find_compatible_door_in_sectors_ex(world, door, available_sectors, player)
|
||||||
if connect_sector is not None:
|
if connect_sector is not None:
|
||||||
logger.info(' Found new sector via %s', connect_door.name)
|
logger.info(' Found new sector via %s', connect_door.name)
|
||||||
if door not in current_sector.outstanding_doors:
|
|
||||||
raise Exception('Door %s was not in sector', door.name)
|
|
||||||
# Check if valid
|
# Check if valid
|
||||||
if not is_valid(door, connect_door, current_sector, connect_sector, len(available_sectors) == 1):
|
if not is_valid(door, connect_door, current_sector, connect_sector, len(available_sectors) == 1):
|
||||||
logger.info(' Not Linking %s to %s', door.name, connect_door.name)
|
logger.info(' Not Linking %s to %s', door.name, connect_door.name)
|
||||||
available_doors.insert(0, door)
|
current_sector.outstanding_doors.insert(0, door)
|
||||||
|
if len(current_sector.outstanding_doors) <= 1:
|
||||||
|
raise Exception('Rejected last option due to dead end... infinite loop ensues')
|
||||||
continue
|
continue
|
||||||
# Apply connection and add the new region's doors to the available list
|
# Apply connection and add the new region's doors to the available list
|
||||||
maybe_connect_two_way(world, door, connect_door, player)
|
maybe_connect_two_way(world, door, connect_door, player)
|
||||||
current_sector.outstanding_doors.remove(door)
|
|
||||||
connect_sector.outstanding_doors.remove(connect_door)
|
connect_sector.outstanding_doors.remove(connect_door)
|
||||||
available_doors.extend(connect_sector.outstanding_doors)
|
|
||||||
available_sectors.remove(connect_sector)
|
available_sectors.remove(connect_sector)
|
||||||
current_sector.outstanding_doors.extend(connect_sector.outstanding_doors)
|
current_sector.outstanding_doors.extend(connect_sector.outstanding_doors)
|
||||||
current_sector.regions.extend(connect_sector.regions)
|
current_sector.regions.extend(connect_sector.regions)
|
||||||
else:
|
else:
|
||||||
# If there's no available region with a door, use an internal connection
|
# If there's no available region with a door, use an internal connection
|
||||||
connect_door = find_compatible_door_in_list_old(world, door, available_doors, player)
|
connect_door = find_compatible_door_in_list_old(world, door, current_sector.outstanding_doors, player)
|
||||||
if connect_door is not None:
|
if connect_door is not None:
|
||||||
logger.info(' Adding loop via %s', connect_door.name)
|
logger.info(' Adding loop via %s', connect_door.name)
|
||||||
if door not in current_sector.outstanding_doors:
|
|
||||||
raise Exception('Door %s was not in sector', door.name)
|
|
||||||
# Check if valid
|
# Check if valid
|
||||||
if not is_loop_valid(door, connect_door, current_sector):
|
if not is_loop_valid(door, connect_door, current_sector, len(available_sectors) == 0):
|
||||||
logger.info(' Not Linking %s to %s', door.name, connect_door.name)
|
logger.info(' Not Linking %s to %s', door.name, connect_door.name)
|
||||||
available_doors.insert(0, door)
|
current_sector.outstanding_doors.insert(0, door)
|
||||||
|
if len(current_sector.outstanding_doors) <= 1:
|
||||||
|
raise Exception('Rejected last option due to dead end...')
|
||||||
continue
|
continue
|
||||||
maybe_connect_two_way(world, door, connect_door, player)
|
maybe_connect_two_way(world, door, connect_door, player)
|
||||||
current_sector.outstanding_doors.remove(door)
|
|
||||||
current_sector.outstanding_doors.remove(connect_door)
|
current_sector.outstanding_doors.remove(connect_door)
|
||||||
else:
|
else:
|
||||||
raise Exception ('Something has gone terribly wrong')
|
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(available_doors) > 0:
|
if len(available_sectors) > 0 or len(current_sector.outstanding_doors) > 0:
|
||||||
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.')
|
||||||
|
|
||||||
|
|
||||||
@@ -984,8 +979,14 @@ def is_valid(door_a, door_b, sector_a, sector_b, last_sector):
|
|||||||
return False # not sure how we got here, but it's a bad idea
|
return False # not sure how we got here, but it's a bad idea
|
||||||
|
|
||||||
|
|
||||||
def is_loop_valid(door_a, door_b, sector):
|
def is_loop_valid(door_a, door_b, sector, no_more_sectors):
|
||||||
return True # todo: is this always true?
|
if no_more_sectors:
|
||||||
|
return True
|
||||||
|
elif not door_a.blocked and not door_b.blocked:
|
||||||
|
return sector.outflow() - 2 > 0
|
||||||
|
elif door_a.blocked or door_b.blocked:
|
||||||
|
return sector.outflow() - 1 > 0
|
||||||
|
return True # todo: is this always true? both blocked but we're connecting loops now, so dead end?
|
||||||
|
|
||||||
|
|
||||||
# DATA GOES DOWN HERE
|
# DATA GOES DOWN HERE
|
||||||
|
|||||||
@@ -174,7 +174,7 @@ hyrule_castle_regions = [
|
|||||||
'Hyrule Dungeon South Abyss Catwalk', 'Hyrule Dungeon Guardroom', 'Hyrule Dungeon Armory Main',
|
'Hyrule Dungeon South Abyss Catwalk', 'Hyrule Dungeon Guardroom', 'Hyrule Dungeon Armory Main',
|
||||||
'Hyrule Dungeon Armory North Branch', 'Hyrule Dungeon Staircase', 'Hyrule Dungeon Cellblock',
|
'Hyrule Dungeon Armory North Branch', 'Hyrule Dungeon Staircase', 'Hyrule Dungeon Cellblock',
|
||||||
'Sewers Behind Tapestry', 'Sewers Rope Room', 'Sewers Dark Cross', 'Sewers Water', 'Sewers Key Rat',
|
'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'
|
'Sewers Secret Room Blocked Path', 'Sewers Secret Room', 'Sewers Pull Switch', 'Sanctuary'
|
||||||
]
|
]
|
||||||
|
|
||||||
eastern_regions = [
|
eastern_regions = [
|
||||||
|
|||||||
Reference in New Issue
Block a user