def shuffle_dungeon(world, player, start_region_names, dungeon_region_names):
    logger = logging.getLogger('')
    available_regions = []
    for name in [r for r in dungeon_region_names if (r not in start_region_names)]:
        available_regions.append(world.get_region(name, player))
    random.shuffle(available_regions)
    ugly_regions = {}
    next_ugly_region = 1
    available_doors = []
    for name in start_region_names:
        logger.info('Starting in %s', name)
        for door in get_doors(world, world.get_region(name, player), player):
            ugly_regions[door.name] = 0
            available_doors.append(door)
    while (len(available_doors) > 0):
        random.shuffle(available_doors)
        available_doors.sort(key=(lambda door: (1 if door.blocked else (0 if door.ugly else 2))))
        door = available_doors.pop()
        logger.info('Linking %s', door.name)
        (connect_region, connect_door) = find_compatible_door_in_regions(world, door, available_regions, player)
        if ((connect_region is not None) and (not door.blocked)):
            logger.info('  Found new region %s via %s', connect_region.name, connect_door.name)
            maybe_connect_two_way(world, door, connect_door, player)
            new_room_ugly_region = ugly_regions[door.name]
            if connect_door.ugly:
                next_ugly_region += 1
                new_room_ugly_region = next_ugly_region
            is_new_region = (connect_region in available_regions)
            for door in get_doors(world, connect_region, player):
                ugly_regions[door.name] = new_room_ugly_region
                if is_new_region:
                    available_doors.append(door)
                if ((door != connect_door) and door.ugly):
                    logger.info('Failed because of ugly door, trying again.')
                    shuffle_dungeon(world, player, start_region_names, dungeon_region_names)
                    return
            if is_new_region:
                available_regions.remove(connect_region)
            if (connect_door in available_doors):
                available_doors.remove(connect_door)
        else:
            connect_door = find_compatible_door_in_list(ugly_regions, 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)
                if (connect_door in available_doors):
                    available_doors.remove(connect_door)
    if ((len(available_regions) > 0) or (len(available_doors) > 0)):
        logger.info('Failed to add all regions to dungeon, trying again.')
        shuffle_dungeon(world, player, start_region_names, dungeon_region_names)
        return
def shuffle_dungeon(world, player, start_region_names, dungeon_region_names):
    logger = logging.getLogger()
    available_regions = []
    for name in [r for r in dungeon_region_names if (r not in start_region_names)]:
        available_regions.append(world.get_region(name, player))
    random.shuffle(available_regions)
    ugly_regions = {}
    next_ugly_region = 1
    available_doors = []
    for name in start_region_names:
        logger.info('Starting in %s', name)
        for door in get_doors(world, world.get_region(name, player), player):
            ugly_regions[door.name] = 0
            available_doors.append(door)
    while (len(available_doors) > 0):
        random.shuffle(available_doors)
        available_doors.sort(key=(lambda door: (1 if door.blocked else (0 if door.ugly else 2))))
        door = available_doors.pop()
        logger.info('Linking %s', door.name)
        (connect_region, connect_door) = find_compatible_door_in_regions(world, door, available_regions, player)
        if ((connect_region is not None) and (not door.blocked)):
            logger.info('  Found new region %s via %s', connect_region.name, connect_door.name)
            maybe_connect_two_way(world, door, connect_door, player)
            new_room_ugly_region = ugly_regions[door.name]
            if connect_door.ugly:
                next_ugly_region += 1
                new_room_ugly_region = next_ugly_region
            is_new_region = (connect_region in available_regions)
            for door in get_doors(world, connect_region, player):
                ugly_regions[door.name] = new_room_ugly_region
                if is_new_region:
                    available_doors.append(door)
                if ((door != connect_door) and door.ugly):
                    logger.info('Failed because of ugly door, trying again.')
                    shuffle_dungeon(world, player, start_region_names, dungeon_region_names)
                    return
            if is_new_region:
                available_regions.remove(connect_region)
            if (connect_door in available_doors):
                available_doors.remove(connect_door)
        else:
            connect_door = find_compatible_door_in_list(ugly_regions, 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)
                if (connect_door in available_doors):
                    available_doors.remove(connect_door)
    if ((len(available_regions) > 0) or (len(available_doors) > 0)):
        logger.info('Failed to add all regions to dungeon, trying again.')
        shuffle_dungeon(world, player, start_region_names, dungeon_region_names)
        return