Ejemplo n.º 1
0
def copy_world(world):
    # ToDo: Not good yet
    ret = World(world.shuffle, world.logic, world.mode, world.difficulty, world.timer, world.progressive, world.goal, world.algorithm, world.place_dungeon_items, world.check_beatable_only, world.shuffle_ganon, world.quickswap, world.fastmenu, world.disable_music, world.keysanity, world.retro, world.custom, world.customitemarray)
    ret.required_medallions = list(world.required_medallions)
    ret.swamp_patch_required = world.swamp_patch_required
    ret.ganon_at_pyramid = world.ganon_at_pyramid
    ret.treasure_hunt_count = world.treasure_hunt_count
    ret.treasure_hunt_icon = world.treasure_hunt_icon
    ret.sewer_light_cone = world.sewer_light_cone
    ret.light_world_light_cone = world.light_world_light_cone
    ret.dark_world_light_cone = world.dark_world_light_cone
    ret.seed = world.seed
    ret.can_access_trock_eyebridge = world.can_access_trock_eyebridge
    ret.can_take_damage = world.can_take_damage
    ret.difficulty_requirements = world.difficulty_requirements
    ret.fix_fake_world = world.fix_fake_world
    ret.lamps_needed_for_dark_rooms = world.lamps_needed_for_dark_rooms
    create_regions(ret)
    create_dungeons(ret)

    copy_dynamic_regions_and_locations(world, ret)

    for shop in world.shops:
        copied_shop = ret.get_region(shop.region.name).shop
        copied_shop.active = shop.active
        copied_shop.inventory = copy.copy(shop.inventory)

    # connect copied world
    for region in world.regions:
        copied_region = ret.get_region(region.name)
        copied_region.is_light_world = region.is_light_world
        copied_region.is_dark_world = region.is_dark_world
        for entrance in region.entrances:
            ret.get_entrance(entrance.name).connect(copied_region)

    # fill locations
    for location in world.get_locations():
        if location.item is not None:
            item = Item(location.item.name, location.item.advancement, location.item.priority, location.item.type)
            ret.get_location(location.name).item = item
            item.location = ret.get_location(location.name)
        if location.event:
            ret.get_location(location.name).event = True

    # copy remaining itempool. No item in itempool should have an assigned location
    for item in world.itempool:
        ret.itempool.append(Item(item.name, item.advancement, item.priority, item.type))

    # copy progress items in state
    ret.state.prog_items = list(world.state.prog_items)

    set_rules(ret)

    return ret
Ejemplo n.º 2
0
def copy_world(world):
    # ToDo: Not good yet
    ret = World(world.players, world.shuffle, world.logic, world.mode,
                world.swords, world.difficulty, world.difficulty_adjustments,
                world.timer, world.progressive, world.goal, world.algorithm,
                world.accessibility, world.shuffle_ganon, world.retro,
                world.custom, world.customitemarray, world.hints)
    ret.teams = world.teams
    ret.player_names = copy.deepcopy(world.player_names)
    ret.remote_items = world.remote_items.copy()
    ret.required_medallions = world.required_medallions.copy()
    ret.swamp_patch_required = world.swamp_patch_required.copy()
    ret.ganon_at_pyramid = world.ganon_at_pyramid.copy()
    ret.powder_patch_required = world.powder_patch_required.copy()
    ret.ganonstower_vanilla = world.ganonstower_vanilla.copy()
    ret.treasure_hunt_count = world.treasure_hunt_count.copy()
    ret.treasure_hunt_icon = world.treasure_hunt_icon.copy()
    ret.sewer_light_cone = world.sewer_light_cone.copy()
    ret.light_world_light_cone = world.light_world_light_cone
    ret.dark_world_light_cone = world.dark_world_light_cone
    ret.seed = world.seed
    ret.can_access_trock_eyebridge = world.can_access_trock_eyebridge.copy()
    ret.can_access_trock_front = world.can_access_trock_front.copy()
    ret.can_access_trock_big_chest = world.can_access_trock_big_chest.copy()
    ret.can_access_trock_middle = world.can_access_trock_middle.copy()
    ret.can_take_damage = world.can_take_damage
    ret.difficulty_requirements = world.difficulty_requirements.copy()
    ret.fix_fake_world = world.fix_fake_world.copy()
    ret.lamps_needed_for_dark_rooms = world.lamps_needed_for_dark_rooms
    ret.mapshuffle = world.mapshuffle.copy()
    ret.compassshuffle = world.compassshuffle.copy()
    ret.keyshuffle = world.keyshuffle.copy()
    ret.bigkeyshuffle = world.bigkeyshuffle.copy()
    ret.crystals_needed_for_ganon = world.crystals_needed_for_ganon.copy()
    ret.crystals_needed_for_gt = world.crystals_needed_for_gt.copy()
    ret.open_pyramid = world.open_pyramid.copy()
    ret.boss_shuffle = world.boss_shuffle.copy()
    ret.enemy_shuffle = world.enemy_shuffle.copy()
    ret.enemy_health = world.enemy_health.copy()
    ret.enemy_damage = world.enemy_damage.copy()
    ret.beemizer = world.beemizer.copy()
    ret.timer = world.timer.copy()
    ret.shufflepots = world.shufflepots.copy()

    for player in range(1, world.players + 1):
        if world.mode[player] != 'inverted':
            create_regions(ret, player)
        else:
            create_inverted_regions(ret, player)
        create_shops(ret, player)
        create_dungeons(ret, player)

    copy_dynamic_regions_and_locations(world, ret)

    # copy bosses
    for dungeon in world.dungeons:
        for level, boss in dungeon.bosses.items():
            ret.get_dungeon(dungeon.name, dungeon.player).bosses[level] = boss

    for shop in world.shops:
        copied_shop = ret.get_region(shop.region.name, shop.region.player).shop
        copied_shop.inventory = copy.copy(shop.inventory)

    # connect copied world
    for region in world.regions:
        copied_region = ret.get_region(region.name, region.player)
        copied_region.is_light_world = region.is_light_world
        copied_region.is_dark_world = region.is_dark_world
        for exit in copied_region.exits:
            old_connection = world.get_entrance(exit.name,
                                                exit.player).connected_region
            exit.connect(
                ret.get_region(old_connection.name, old_connection.player))

    # fill locations
    for location in world.get_locations():
        if location.item is not None:
            item = Item(location.item.name,
                        location.item.advancement,
                        location.item.priority,
                        location.item.type,
                        player=location.item.player)
            ret.get_location(location.name, location.player).item = item
            item.location = ret.get_location(location.name, location.player)
            item.world = ret
        if location.event:
            ret.get_location(location.name, location.player).event = True
        if location.locked:
            ret.get_location(location.name, location.player).locked = True

    # copy remaining itempool. No item in itempool should have an assigned location
    for item in world.itempool:
        ret.itempool.append(
            Item(item.name,
                 item.advancement,
                 item.priority,
                 item.type,
                 player=item.player))

    for item in world.precollected_items:
        ret.push_precollected(ItemFactory(item.name, item.player))

    # copy progress items in state
    ret.state.prog_items = world.state.prog_items.copy()
    ret.state.stale = {player: True for player in range(1, world.players + 1)}

    for player in range(1, world.players + 1):
        set_rules(ret, player)

    return ret
Ejemplo n.º 3
0
def main(args, seed=None):
    start = time.clock()

    # initialize the world
    world = World(args.shuffle, args.logic, args.mode, args.difficulty, args.timer, args.progressive, args.goal, args.algorithm, not args.nodungeonitems, args.beatableonly, args.shuffleganon, args.quickswap, args.fastmenu, args.disablemusic, args.keysanity, args.retro, args.custom, args.customitemarray)
    logger = logging.getLogger('')
    if seed is None:
        random.seed(None)
        world.seed = random.randint(0, 999999999)
    else:
        world.seed = int(seed)
    random.seed(world.seed)

    logger.info('ALttP Entrance Randomizer Version %s  -  Seed: %s\n\n', __version__, world.seed)

    world.difficulty_requirements = difficulties[world.difficulty]

    create_regions(world)

    create_dungeons(world)

    logger.info('Shuffling the World about.')

    link_entrances(world)
    mark_light_world_regions(world)

    logger.info('Calculating Access Rules.')

    set_rules(world)

    logger.info('Generating Item Pool.')

    generate_itempool(world)

    logger.info('Placing Dungeon Items.')

    shuffled_locations = None
    if args.algorithm in ['balanced', 'vt26'] or args.keysanity:
        shuffled_locations = world.get_unfilled_locations()
        random.shuffle(shuffled_locations)
        fill_dungeons_restrictive(world, shuffled_locations)
    else:
        fill_dungeons(world)

    logger.info('Fill the world.')

    if args.algorithm == 'flood':
        flood_items(world)  # different algo, biased towards early game progress items
    elif args.algorithm == 'vt21':
        distribute_items_cutoff(world, 1)
    elif args.algorithm == 'vt22':
        distribute_items_cutoff(world, 0.66)
    elif args.algorithm == 'freshness':
        distribute_items_staleness(world)
    elif args.algorithm == 'vt25':
        distribute_items_restrictive(world, 0)
    elif args.algorithm == 'vt26':

        distribute_items_restrictive(world, gt_filler(world), shuffled_locations)
    elif args.algorithm == 'balanced':
        distribute_items_restrictive(world, gt_filler(world))

    logger.info('Calculating playthrough.')

    create_playthrough(world)

    logger.info('Patching ROM.')

    if args.sprite is not None:
        if isinstance(args.sprite, Sprite):
            sprite = args.sprite
        else:
            sprite = Sprite(args.sprite)
    else:
        sprite = None

    outfilebase = 'ER_%s_%s-%s-%s%s_%s-%s%s%s%s_%s' % (world.logic, world.difficulty, world.mode, world.goal, "" if world.timer in ['none', 'display'] else "-" + world.timer, world.shuffle, world.algorithm, "-keysanity" if world.keysanity else "", "-retro" if world.retro else "", "-prog_" + world.progressive if world.progressive in ['off', 'random'] else "", world.seed)

    if not args.suppress_rom:
        if args.jsonout:
            rom = JsonRom()
        else:
            rom = LocalRom(args.rom)
        patch_rom(world, rom, bytearray(logic_hash), args.heartbeep, args.heartcolor, sprite)
        if args.jsonout:
            print(json.dumps({'patch': rom.patches, 'spoiler': world.spoiler.to_json()}))
        else:
            rom.write_to_file(args.jsonout or output_path('%s.sfc' % outfilebase))

    if args.create_spoiler and not args.jsonout:
        world.spoiler.to_file(output_path('%s_Spoiler.txt' % outfilebase))

    logger.info('Done. Enjoy.')
    logger.debug('Total Time: %s', time.clock() - start)

    return world
Ejemplo n.º 4
0
def main(args):
    start_time = time.perf_counter()

    # initialize the world
    world = World(1, 'vanilla', 'noglitches', 'standard', 'normal', 'none',
                  'on', 'ganon', 'freshness', False, False, False,
                  args.quickswap, args.fastmenu, args.disablemusic, False,
                  False, False, None, 'none', False)
    logger = logging.getLogger('')

    hasher = hashlib.md5()
    with open(args.plando, 'rb') as plandofile:
        buf = plandofile.read()
        hasher.update(buf)
    world.seed = int(hasher.hexdigest(), 16) % 1000000000

    random.seed(world.seed)

    logger.info('ALttP Plandomizer Version %s  -  Seed: %s\n\n', __version__,
                args.plando)

    world.difficulty_requirements = difficulties[world.difficulty]

    create_regions(world, 1)
    create_dungeons(world, 1)

    link_entrances(world, 1)

    logger.info('Calculating Access Rules.')

    set_rules(world, 1)

    logger.info('Fill the world.')

    text_patches = []

    fill_world(world, args.plando, text_patches)

    if world.get_entrance(
            'Dam', 1).connected_region.name != 'Dam' or world.get_entrance(
                'Swamp Palace',
                1).connected_region.name != 'Swamp Palace (Entrance)':
        world.swamp_patch_required[1] = True

    logger.info('Calculating playthrough.')

    try:
        create_playthrough(world)
    except RuntimeError:
        if args.ignore_unsolvable:
            pass
        else:
            raise

    logger.info('Patching ROM.')

    if args.sprite is not None:
        sprite = Sprite(args.sprite)
    else:
        sprite = None

    rom = LocalRom(args.rom)
    patch_rom(world, 1, rom, args.heartbeep, args.heartcolor, sprite)

    for textname, texttype, text in text_patches:
        if texttype == 'text':
            write_string_to_rom(rom, textname, text)
        #elif texttype == 'credit':
        #    write_credits_string_to_rom(rom, textname, text)

    outfilebase = 'Plando_%s_%s' % (os.path.splitext(
        os.path.basename(args.plando))[0], world.seed)

    rom.write_to_file('%s.sfc' % outfilebase)
    if args.create_spoiler:
        world.spoiler.to_file('%s_Spoiler.txt' % outfilebase)

    logger.info('Done. Enjoy.')
    logger.debug('Total Time: %s', time.perf_counter() - start_time)

    return world
Ejemplo n.º 5
0
def main(args, seed=None):
    start = time.perf_counter()

    # initialize the world
    world = World(args.multi, args.shuffle, args.logic, args.mode, args.swords,
                  args.difficulty, args.item_functionality, args.timer,
                  args.progressive, args.goal, args.algorithm,
                  not args.nodungeonitems, args.accessibility,
                  args.shuffleganon, args.quickswap, args.fastmenu,
                  args.disablemusic, args.keysanity, args.retro, args.custom,
                  args.customitemarray, args.shufflebosses, args.hints)
    logger = logging.getLogger('')
    if seed is None:
        random.seed(None)
        world.seed = random.randint(0, 999999999)
    else:
        world.seed = int(seed)
    random.seed(world.seed)

    world.crystals_needed_for_ganon = random.randint(
        0, 7) if args.crystals_ganon == 'random' else int(args.crystals_ganon)
    world.crystals_needed_for_gt = random.randint(
        0, 7) if args.crystals_gt == 'random' else int(args.crystals_gt)

    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)

    world.difficulty_requirements = difficulties[world.difficulty]

    if world.mode != 'inverted':
        for player in range(1, world.players + 1):
            create_regions(world, player)
            create_dungeons(world, player)
    else:
        for player in range(1, world.players + 1):
            create_inverted_regions(world, player)
            create_dungeons(world, player)

    logger.info('Shuffling the World about.')

    if world.mode != 'inverted':
        for player in range(1, world.players + 1):
            link_entrances(world, player)

        mark_light_world_regions(world)
    else:
        for player in range(1, world.players + 1):
            link_inverted_entrances(world, player)

        mark_dark_world_regions(world)

    logger.info('Generating Item Pool.')

    for player in range(1, world.players + 1):
        generate_itempool(world, player)

    logger.info('Calculating Access Rules.')

    for player in range(1, world.players + 1):
        set_rules(world, player)

    logger.info('Placing Dungeon Prizes.')

    fill_prizes(world)

    logger.info('Placing Dungeon Items.')

    shuffled_locations = None
    if args.algorithm in ['balanced', 'vt26'] or args.keysanity:
        shuffled_locations = world.get_unfilled_locations()
        random.shuffle(shuffled_locations)
        fill_dungeons_restrictive(world, shuffled_locations)
    else:
        fill_dungeons(world)

    logger.info('Fill the world.')

    if args.algorithm == 'flood':
        flood_items(
            world)  # different algo, biased towards early game progress items
    elif args.algorithm == 'vt21':
        distribute_items_cutoff(world, 1)
    elif args.algorithm == 'vt22':
        distribute_items_cutoff(world, 0.66)
    elif args.algorithm == 'freshness':
        distribute_items_staleness(world)
    elif args.algorithm == 'vt25':
        distribute_items_restrictive(world, 0)
    elif args.algorithm == 'vt26':

        distribute_items_restrictive(world, gt_filler(world),
                                     shuffled_locations)
    elif args.algorithm == 'balanced':
        distribute_items_restrictive(world, gt_filler(world))

    if world.players > 1:
        logger.info('Balancing multiworld progression.')
        balance_multiworld_progression(world)

    logger.info('Patching ROM.')

    if args.sprite is not None:
        if isinstance(args.sprite, Sprite):
            sprite = args.sprite
        else:
            sprite = Sprite(args.sprite)
    else:
        sprite = None

    outfilebase = 'ER_%s_%s-%s-%s-%s%s_%s-%s%s%s%s%s_%s' % (
        world.logic, world.difficulty, world.difficulty_adjustments,
        world.mode, world.goal, "" if world.timer in ['none', 'display'] else
        "-" + world.timer, world.shuffle, world.algorithm, "-keysanity"
        if world.keysanity else "", "-retro" if world.retro else "", "-prog_" +
        world.progressive if world.progressive in ['off', 'random'] else "",
        "-nohints" if not world.hints else "", world.seed)

    use_enemizer = args.enemizercli and (
        args.shufflebosses != 'none' or args.shuffleenemies
        or args.enemy_health != 'default' or args.enemy_health != 'default'
        or args.enemy_damage or args.shufflepalette or args.shufflepots)

    jsonout = {}
    if not args.suppress_rom:
        if world.players > 1:
            raise NotImplementedError(
                "Multiworld rom writes have not been implemented")
        else:
            player = 1

            local_rom = None
            if args.jsonout:
                rom = JsonRom()
            else:
                if use_enemizer:
                    local_rom = LocalRom(args.rom)
                    rom = JsonRom()
                else:
                    rom = LocalRom(args.rom)

            patch_rom(world, player, rom)

            enemizer_patch = []
            if use_enemizer:
                enemizer_patch = get_enemizer_patch(
                    world, player, rom, args.rom, args.enemizercli,
                    args.shuffleenemies, args.enemy_health, args.enemy_damage,
                    args.shufflepalette, args.shufflepots)

            if args.jsonout:
                jsonout['patch'] = rom.patches
                if use_enemizer:
                    jsonout['enemizer' % player] = enemizer_patch
            else:
                if use_enemizer:
                    local_rom.patch_enemizer(
                        rom.patches,
                        os.path.join(os.path.dirname(args.enemizercli),
                                     "enemizerBasePatch.json"), enemizer_patch)
                    rom = local_rom

                apply_rom_settings(rom, args.heartbeep, args.heartcolor,
                                   world.quickswap, world.fastmenu,
                                   world.disable_music, sprite)
                rom.write_to_file(output_path('%s.sfc' % outfilebase))

    if args.create_spoiler and not args.jsonout:
        world.spoiler.to_file(output_path('%s_Spoiler.txt' % outfilebase))

    if not args.skip_playthrough:
        logger.info('Calculating playthrough.')
        create_playthrough(world)

    if args.jsonout:
        print(json.dumps({**jsonout, 'spoiler': world.spoiler.to_json()}))
    elif args.create_spoiler and not args.skip_playthrough:
        world.spoiler.to_file(output_path('%s_Spoiler.txt' % outfilebase))

    logger.info('Done. Enjoy.')
    logger.debug('Total Time: %s', time.perf_counter() - start)

    return world