def adjust(args):
    start = time.process_time()
    logger = logging.getLogger('')
    logger.info('Patching ROM.')

    outfilebase = os.path.basename(args.rom)[:-4] + '_adjusted'

    if os.stat(args.rom).st_size in (0x200000, 0x400000) and os.path.splitext(
            args.rom)[-1].lower() == '.sfc':
        rom = LocalRom(args.rom, False)
        if os.path.isfile(args.baserom):
            baserom = LocalRom(args.baserom, True)
            rom.orig_buffer = baserom.orig_buffer
    else:
        raise RuntimeError(
            'Provided Rom is not a valid Link to the Past Randomizer Rom. Please provide one for adjusting.'
        )

    apply_rom_settings(rom, args.heartbeep, args.heartcolor, args.quickswap,
                       args.fastmenu, args.disablemusic, args.sprite,
                       args.ow_palettes, args.uw_palettes)

    rom.write_to_file(output_path('%s.sfc' % outfilebase))

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

    return args
def adjust(args):
    start = time.clock()
    logger = logging.getLogger('')
    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 = os.path.basename(args.rom)[:-4] + '_adjusted'

    if os.stat(args.rom).st_size == 2097152 and os.path.splitext(
            args.rom)[-1].lower() == '.sfc':
        rom = LocalRom(args.rom, False)
    else:
        raise RuntimeError(
            'Provided Rom is not a valid Link to the Past Randomizer Rom. Please provide one for adjusting.'
        )

    apply_rom_settings(rom, args.heartbeep, args.heartcolor, args.quickswap,
                       args.fastmenu, args.disablemusic, sprite)

    rom.write_to_file(output_path('%s.sfc' % outfilebase))

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

    return args
def adjust(args):
    start = time.perf_counter()
    logger = logging.getLogger('Adjuster')
    logger.info('Patching ROM.')

    if os.path.splitext(args.rom)[-1].lower() == '.bmbp':
        import Patch
        meta, args.rom = Patch.create_rom_file(args.rom)

    if os.stat(args.rom).st_size in (0x200000, 0x400000) and os.path.splitext(
            args.rom)[-1].lower() == '.sfc':
        rom = LocalRom(args.rom, patch=False)
    else:
        raise RuntimeError(
            'Provided Rom is not a valid Link to the Past Randomizer Rom. Please provide one for adjusting.'
        )

    apply_rom_settings(rom, args.heartbeep, args.heartcolor, args.quickswap,
                       args.fastmenu, args.disablemusic, args.sprite,
                       args.ow_palettes, args.uw_palettes)
    path = output_path(f'{os.path.basename(args.rom)[:-4]}_adjusted.sfc')
    rom.write_to_file(path)

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

    return args, path
예제 #4
0
def adjust(args):
    start = time.perf_counter()
    logger = logging.getLogger('Adjuster')
    logger.info('Patching ROM.')
    vanillaRom = args.baserom
    if os.path.splitext(args.rom)[-1].lower() == '.bmbp':
        import Patch
        meta, args.rom = Patch.create_rom_file(args.rom)

    if os.stat(args.rom).st_size in (0x200000, 0x400000) and os.path.splitext(
            args.rom)[-1].lower() == '.sfc':
        rom = LocalRom(args.rom, patch=False, vanillaRom=vanillaRom)
    else:
        raise RuntimeError(
            'Provided Rom is not a valid Link to the Past Randomizer Rom. Please provide one for adjusting.'
        )
    palettes_options = {}
    palettes_options['dungeon'] = args.uw_palettes

    palettes_options['overworld'] = args.ow_palettes
    palettes_options['hud'] = args.hud_palettes
    palettes_options['sword'] = args.sword_palettes
    palettes_options['shield'] = args.shield_palettes
    # palettes_options['link']=args.link_palettesvera
    racerom = rom.read_byte(0x180213) > 0

    apply_rom_settings(
        rom,
        args.heartbeep,
        args.heartcolor,
        args.quickswap,
        args.fastmenu,
        args.disablemusic,
        args.sprite,
        palettes_options,
        cutscenespeed=args.cutscenespeed if not racerom else "normal",
        reduceflashing=args.reduceflashing)
    path = output_path(f'{os.path.basename(args.rom)[:-4]}_adjusted.sfc')
    rom.write_to_file(path)

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

    return args, path
예제 #5
0
    def _gen_rom(team: int, player: int):
        sprite_random_on_hit = type(
            args.sprite[player]) is str and args.sprite[player].lower(
            ) == 'randomonhit'
        use_enemizer = (world.boss_shuffle[player] != 'none'
                        or world.enemy_shuffle[player] != 'none'
                        or world.enemy_health[player] != 'default'
                        or world.enemy_damage[player] != 'default'
                        or args.shufflepots[player] or sprite_random_on_hit)

        rom = LocalRom(args.rom)

        patch_rom(world, rom, player, team, use_enemizer)

        if use_enemizer:
            patch_enemizer(world, player, rom, args.enemizercli,
                           sprite_random_on_hit)

        if args.race:
            patch_race_rom(rom)

        world.spoiler.hashes[(player, team)] = get_hash_string(rom.hash)

        apply_rom_settings(rom, args.heartbeep[player],
                           args.heartcolor[player], args.quickswap[player],
                           args.fastmenu[player], args.disablemusic[player],
                           args.sprite[player], args.ow_palettes[player],
                           args.uw_palettes[player])

        mcsb_name = ''
        if all([
                world.mapshuffle[player], world.compassshuffle[player],
                world.keyshuffle[player], world.bigkeyshuffle[player]
        ]):
            mcsb_name = '-keysanity'
        elif [
                world.mapshuffle[player], world.compassshuffle[player],
                world.keyshuffle[player], world.bigkeyshuffle[player]
        ].count(True) == 1:
            mcsb_name = '-mapshuffle' if world.mapshuffle[
                player] else '-compassshuffle' if world.compassshuffle[
                    player] else '-keyshuffle' if world.keyshuffle[
                        player] else '-bigkeyshuffle'
        elif any([
                world.mapshuffle[player], world.compassshuffle[player],
                world.keyshuffle[player], world.bigkeyshuffle[player]
        ]):
            mcsb_name = '-%s%s%s%sshuffle' % (
                'M' if world.mapshuffle[player] else '',
                'C' if world.compassshuffle[player] else '',
                'S' if world.keyshuffle[player] else '',
                'B' if world.bigkeyshuffle[player] else '')

        outfilepname = f'_T{team + 1}' if world.teams > 1 else ''
        if world.players > 1:
            outfilepname += f'_P{player}'
        if world.players > 1 or world.teams > 1:
            outfilepname += f"_{world.player_names[player][team].replace(' ', '_')}" if world.player_names[
                player][team] != 'Player%d' % player else ''
        outfilesuffix = (
            '_%s_%s-%s-%s-%s%s_%s-%s%s%s%s%s' %
            (world.logic[player], world.difficulty[player],
             world.difficulty_adjustments[player], world.mode[player],
             world.goal[player],
             "" if world.timer[player] in [False, 'display'] else "-" +
             world.timer[player], world.shuffle[player], world.algorithm,
             mcsb_name, "-retro" if world.retro[player] else "",
             "-prog_" + world.progressive[player] if world.progressive[player]
             in ['off', 'random'] else "", "-nohints" if
             not world.hints[player] else "")) if not args.outputname else ''
        rompath = output_path(
            f'{outfilebase}{outfilepname}{outfilesuffix}.sfc')
        rom.write_to_file(rompath)
        if args.create_diff:
            import Patch
            Patch.create_patch_file(rompath)
        return (player, team, list(rom.name))
예제 #6
0
    def _gen_rom(team: int, player: int):
        use_enemizer = (world.boss_shuffle[player] != 'none'
                        or world.enemy_shuffle[player]
                        or world.enemy_health[player] != 'default'
                        or world.enemy_damage[player] != 'default'
                        or world.shufflepots[player]
                        or world.bush_shuffle[player]
                        or world.killable_thieves[player])

        rom = LocalRom(args.rom)

        patch_rom(world, rom, player, team, use_enemizer)

        if use_enemizer:
            patch_enemizer(world, team, player, rom, args.enemizercli)

        if args.race:
            patch_race_rom(rom, world, player)

        world.spoiler.hashes[(player, team)] = get_hash_string(rom.hash)

        palettes_options = {}
        palettes_options['dungeon'] = args.uw_palettes[player]
        palettes_options['overworld'] = args.ow_palettes[player]
        palettes_options['hud'] = args.hud_palettes[player]
        palettes_options['sword'] = args.sword_palettes[player]
        palettes_options['shield'] = args.shield_palettes[player]
        palettes_options['link'] = args.link_palettes[player]

        apply_rom_settings(rom, args.heartbeep[player],
                           args.heartcolor[player], args.quickswap[player],
                           args.fastmenu[player], args.disablemusic[player],
                           args.sprite[player], palettes_options, world,
                           player, True)

        mcsb_name = ''
        if all([
                world.mapshuffle[player], world.compassshuffle[player],
                world.keyshuffle[player], world.bigkeyshuffle[player]
        ]):
            mcsb_name = '-keysanity'
        elif [
                world.mapshuffle[player], world.compassshuffle[player],
                world.keyshuffle[player], world.bigkeyshuffle[player]
        ].count(True) == 1:
            mcsb_name = '-mapshuffle' if world.mapshuffle[player] else \
                '-compassshuffle' if world.compassshuffle[player] else \
                '-universal_keys' if world.keyshuffle[player] == "universal" else \
                '-keyshuffle' if world.keyshuffle[player] else '-bigkeyshuffle'
        elif any([
                world.mapshuffle[player], world.compassshuffle[player],
                world.keyshuffle[player], world.bigkeyshuffle[player]
        ]):
            mcsb_name = '-%s%s%s%sshuffle' % (
                'M' if world.mapshuffle[player] else '',
                'C' if world.compassshuffle[player] else '',
                'U' if world.keyshuffle[player] == "universal" else
                'S' if world.keyshuffle[player] else '',
                'B' if world.bigkeyshuffle[player] else '')

        outfilepname = f'_T{team + 1}' if world.teams > 1 else ''
        outfilepname += f'_P{player}'
        outfilepname += f"_{world.player_names[player][team].replace(' ', '_')}" \
            if world.player_names[player][team] != 'Player%d' % player else ''
        outfilestuffs = {
            "logic": world.logic[player],  # 0
            "difficulty": world.difficulty[player],  # 1
            "item_functionality": world.item_functionality[player],  # 2
            "mode": world.mode[player],  # 3
            "goal": world.goal[player],  # 4
            "timer": str(world.timer[player]),  # 5
            "shuffle": world.shuffle[player],  # 6
            "algorithm": world.algorithm,  # 7
            "mscb": mcsb_name,  # 8
            "retro": world.retro[player],  # 9
            "progressive": world.progressive,  # A
            "hints": 'True' if world.hints[player] else 'False'  # B
        }
        #                  0  1  2  3  4 5  6  7 8 9 A B
        outfilesuffix = (
            '_%s_%s-%s-%s-%s%s_%s-%s%s%s%s%s' % (
                #  0          1      2      3    4     5    6      7     8        9         A     B           C
                # _noglitches_normal-normal-open-ganon-ohko_simple-balanced-keysanity-retro-prog_random-nohints
                # _noglitches_normal-normal-open-ganon     _simple-balanced-keysanity-retro
                # _noglitches_normal-normal-open-ganon     _simple-balanced-keysanity      -prog_random
                # _noglitches_normal-normal-open-ganon     _simple-balanced-keysanity                  -nohints
                outfilestuffs["logic"],  # 0
                outfilestuffs["difficulty"],  # 1
                outfilestuffs["item_functionality"],  # 2
                outfilestuffs["mode"],  # 3
                outfilestuffs["goal"],  # 4
                "" if outfilestuffs["timer"] in ['False', 'none', 'display']
                else "-" + outfilestuffs["timer"],  # 5
                outfilestuffs["shuffle"],  # 6
                outfilestuffs["algorithm"],  # 7
                outfilestuffs["mscb"],  # 8
                "-retro" if outfilestuffs["retro"] == "True" else "",  # 9
                "-prog_" + outfilestuffs["progressive"] if
                outfilestuffs["progressive"] in ['off', 'random'] else "",  # A
                "-nohints" if not outfilestuffs["hints"] == "True" else ""
            )  # B
        ) if not args.outputname else ''
        rompath = output_path(
            f'{outfilebase}{outfilepname}{outfilesuffix}.sfc')
        rom.write_to_file(rompath, hide_enemizer=True)
        if args.create_diff:
            Patch.create_patch_file(rompath)
        return player, team, bytes(rom.name).decode()
예제 #7
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, False,
                  False, False, None, False)
    world.player_names[1].append("Player1")
    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[1] = difficulties[world.difficulty[1]]

    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.')

    rom = LocalRom(args.rom)
    patch_rom(world, rom, 1, 1, False)

    apply_rom_settings(rom, args.heartbeep, args.heartcolor, args.quickswap,
                       args.fastmenu, args.disablemusic, args.sprite,
                       args.ow_palettes, args.uw_palettes)

    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
예제 #8
0
def main(args, seed=None):
    if args.outputpath:
        os.makedirs(args.outputpath, exist_ok=True)
        output_path.cached_path = args.outputpath

    start = time.process_time()

    # 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,
                  args.accessibility, args.shuffleganon, args.retro,
                  args.custom, args.customitemarray, 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.remote_items = args.remote_items.copy()
    world.mapshuffle = args.mapshuffle.copy()
    world.compassshuffle = args.compassshuffle.copy()
    world.keyshuffle = args.keyshuffle.copy()
    world.bigkeyshuffle = args.bigkeyshuffle.copy()
    world.crystals_needed_for_ganon = {
        player: random.randint(0, 7) if args.crystals_ganon[player] == 'random'
        else int(args.crystals_ganon[player])
        for player in range(1, world.players + 1)
    }
    world.crystals_needed_for_gt = {
        player: random.randint(0, 7) if args.crystals_gt[player] == 'random'
        else int(args.crystals_gt[player])
        for player in range(1, world.players + 1)
    }
    world.open_pyramid = args.openpyramid.copy()
    world.boss_shuffle = args.shufflebosses.copy()
    world.enemy_shuffle = args.shuffleenemies.copy()
    world.enemy_health = args.enemy_health.copy()
    world.enemy_damage = args.enemy_damage.copy()
    world.beemizer = args.beemizer.copy()

    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',
                __version__, world.seed)

    parsed_names = parse_player_names(args.names, world.players, args.teams)
    world.teams = len(parsed_names)
    for i, team in enumerate(parsed_names, 1):
        if world.players > 1:
            logger.info('%s%s',
                        'Team%d: ' % i if world.teams > 1 else 'Players: ',
                        ', '.join(team))
        for player, name in enumerate(team, 1):
            world.player_names[player].append(name)
    logger.info('')

    for player in range(1, world.players + 1):
        world.difficulty_requirements[player] = difficulties[
            world.difficulty[player]]

        if world.mode[player] == 'standard' and world.enemy_shuffle[
                player] != 'none':
            world.escape_assist[player].append(
                'bombs'
            )  # enemized escape assumes infinite bombs available and will likely be unbeatable without it

        for tok in filter(None, args.startinventory[player].split(',')):
            item = ItemFactory(tok.strip(), player)
            if item:
                world.push_precollected(item)

        if world.mode[player] != 'inverted':
            create_regions(world, player)
        else:
            create_inverted_regions(world, player)
        create_shops(world, player)
        create_dungeons(world, player)

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

    for player in range(1, world.players + 1):
        if world.mode[player] != 'inverted':
            link_entrances(world, player)
            mark_light_world_regions(world, player)
        else:
            link_inverted_entrances(world, player)
            mark_dark_world_regions(world, player)

    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 any(
            list(args.mapshuffle.values()) +
            list(args.compassshuffle.values()) +
            list(args.keyshuffle.values()) +
            list(args.bigkeyshuffle.values())):
        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, False)
    elif args.algorithm == 'vt26':

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

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

    logger.info('Patching ROM.')

    outfilebase = 'ER_%s' % (args.outputname
                             if args.outputname else world.seed)

    rom_names = []
    jsonout = {}
    if not args.suppress_rom:
        for team in range(world.teams):
            for player in range(1, world.players + 1):
                sprite_random_on_hit = type(
                    args.sprite[player]) is str and args.sprite[player].lower(
                    ) == 'randomonhit'
                use_enemizer = (world.boss_shuffle[player] != 'none'
                                or world.enemy_shuffle[player] != 'none'
                                or world.enemy_health[player] != 'default'
                                or world.enemy_damage[player] != 'default'
                                or args.shufflepots[player]
                                or sprite_random_on_hit)

                rom = JsonRom() if args.jsonout or use_enemizer else LocalRom(
                    args.rom)

                patch_rom(world, rom, player, team, use_enemizer)

                if use_enemizer and (args.enemizercli or not args.jsonout):
                    patch_enemizer(world, player, rom, args.rom,
                                   args.enemizercli, args.shufflepots[player],
                                   sprite_random_on_hit)
                    if not args.jsonout:
                        rom = LocalRom.fromJsonRom(rom, args.rom, 0x400000)

                if args.race:
                    patch_race_rom(rom)

                rom_names.append((player, team, list(rom.name)))
                world.spoiler.hashes[(player,
                                      team)] = get_hash_string(rom.hash)

                apply_rom_settings(
                    rom, args.heartbeep[player], args.heartcolor[player],
                    args.quickswap[player], args.fastmenu[player],
                    args.disablemusic[player], args.sprite[player],
                    args.ow_palettes[player], args.uw_palettes[player])

                if args.jsonout:
                    jsonout[f'patch_t{team}_p{player}'] = rom.patches
                else:
                    mcsb_name = ''
                    if all([
                            world.mapshuffle[player],
                            world.compassshuffle[player],
                            world.keyshuffle[player],
                            world.bigkeyshuffle[player]
                    ]):
                        mcsb_name = '-keysanity'
                    elif [
                            world.mapshuffle[player],
                            world.compassshuffle[player],
                            world.keyshuffle[player],
                            world.bigkeyshuffle[player]
                    ].count(True) == 1:
                        mcsb_name = '-mapshuffle' if world.mapshuffle[
                            player] else '-compassshuffle' if world.compassshuffle[
                                player] else '-keyshuffle' if world.keyshuffle[
                                    player] else '-bigkeyshuffle'
                    elif any([
                            world.mapshuffle[player],
                            world.compassshuffle[player],
                            world.keyshuffle[player],
                            world.bigkeyshuffle[player]
                    ]):
                        mcsb_name = '-%s%s%s%sshuffle' % (
                            'M' if world.mapshuffle[player] else '',
                            'C' if world.compassshuffle[player] else '',
                            'S' if world.keyshuffle[player] else '',
                            'B' if world.bigkeyshuffle[player] else '')

                    outfilepname = f'_T{team+1}' if world.teams > 1 else ''
                    if world.players > 1:
                        outfilepname += f'_P{player}'
                    if world.players > 1 or world.teams > 1:
                        outfilepname += f"_{world.player_names[player][team].replace(' ', '_')}" if world.player_names[
                            player][team] != 'Player %d' % player else ''
                    outfilesuffix = (
                        '_%s_%s-%s-%s-%s%s_%s-%s%s%s%s%s' %
                        (world.logic[player], world.difficulty[player],
                         world.difficulty_adjustments[player],
                         world.mode[player], world.goal[player],
                         "" if world.timer in ['none', 'display'] else "-" +
                         world.timer, world.shuffle[player], world.algorithm,
                         mcsb_name, "-retro" if world.retro[player] else "",
                         "-prog_" + world.progressive
                         if world.progressive in ['off', 'random'] else "",
                         "-nohints" if not world.hints[player] else "")
                    ) if not args.outputname else ''
                    rom.write_to_file(
                        output_path(
                            f'{outfilebase}{outfilepname}{outfilesuffix}.sfc'))

        multidata = zlib.compress(
            json.dumps({
                "names":
                parsed_names,
                "roms":
                rom_names,
                "remote_items": [
                    player for player in range(1, world.players + 1)
                    if world.remote_items[player]
                ],
                "locations": [((location.address, location.player),
                               (location.item.code, location.item.player))
                              for location in world.get_filled_locations()
                              if type(location.address) is int]
            }).encode("utf-8"))
        if args.jsonout:
            jsonout["multidata"] = list(multidata)
        else:
            with open(output_path('%s_multidata' % outfilebase), 'wb') as f:
                f.write(multidata)

    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.process_time() - start)

    return world
예제 #9
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