def gen_game(gen_options, race=False, owner=None, sid=None):
    try:
        target = tempfile.TemporaryDirectory()
        playercount = len(gen_options)
        seed = get_seed()
        random.seed(seed)

        if race:
            random.seed()  # reset to time-based random source

        seedname = "M" + (
            f"{random.randint(0, pow(10, seeddigits) - 1)}".zfill(seeddigits))

        erargs = parse_arguments(['--multi', str(playercount)])
        erargs.seed = seed
        erargs.name = {x: ""
                       for x in range(1, playercount + 1)
                       }  # only so it can be overwrittin in mystery
        erargs.create_spoiler = not race
        erargs.race = race
        erargs.skip_playthrough = race
        erargs.outputname = seedname
        erargs.outputpath = target.name
        erargs.teams = 1
        erargs.progression_balancing = {}
        erargs.create_diff = True

        name_counter = Counter()
        for player, (playerfile,
                     settings) in enumerate(gen_options.items(), 1):
            for k, v in settings.items():
                if v is not None:
                    getattr(erargs, k)[player] = v

            if not erargs.name[player]:
                erargs.name[player] = os.path.splitext(
                    os.path.split(playerfile)[-1])[0]
            erargs.name[player] = handle_name(erargs.name[player], player,
                                              name_counter)

        erargs.names = ",".join(erargs.name[i]
                                for i in range(1, playercount + 1))
        del (erargs.name)

        erargs.skip_progression_balancing = {
            player: not balanced
            for player, balanced in erargs.progression_balancing.items()
        }
        del (erargs.progression_balancing)
        ERmain(erargs, seed)

        return upload_to_db(target.name, owner, sid, race)
    except BaseException as e:
        if sid:
            with db_session:
                gen = Generation.get(id=sid)
                if gen is not None:
                    gen.state = STATE_ERROR
                    gen.meta = (e.__class__.__name__ + ": " + str(e)).encode()
        raise
示例#2
0
def start():
    args = parse_arguments(None)

    if is_bundled() and len(sys.argv) == 1:
        # for the bundled builds, if we have no arguments, the user
        # probably wants the gui. Users of the bundled build who want the command line
        # interface shouuld specify at least one option, possibly setting a value to a
        # default if they like all the defaults
        from Gui import guiMain
        close_console()
        guiMain()
        sys.exit(0)

    # ToDo: Validate files further than mere existance
    if not os.path.isfile(args.rom):
        input(
            'Could not find valid base rom for patching at expected path %s. Please run with -h to see help for further information. \nPress Enter to exit.'
            % args.rom)
        sys.exit(1)
    if any([
            sprite is not None and not os.path.isfile(sprite)
            and not Sprite.get_sprite_from_name(sprite)
            for sprite in args.sprite.values()
    ]):
        input(
            'Could not find link sprite sheet at given location. \nPress Enter to exit.'
        )
        sys.exit(1)

    # set up logger
    loglevel = {
        'error': logging.ERROR,
        'info': logging.INFO,
        'warning': logging.WARNING,
        'debug': logging.DEBUG
    }[args.loglevel]
    logging.basicConfig(format='%(message)s', level=loglevel)

    if args.gui:
        from Gui import guiMain
        guiMain(args)
    elif args.count is not None:
        seed = args.seed
        for _ in range(args.count):
            main(seed=seed, args=args)
            seed = get_seed()
    else:
        main(seed=args.seed, args=args)
示例#3
0
def gen(gen_options, race=False):
    target = tempfile.TemporaryDirectory()
    with target:
        playercount = len(gen_options)
        seed = get_seed()
        random.seed(seed)

        if race:
            random.seed()  # reset to time-based random source

        seedname = "M" + (
            f"{random.randint(0, pow(10, seeddigits) - 1)}".zfill(seeddigits))

        erargs = parse_arguments(['--multi', str(playercount)])
        erargs.seed = seed
        erargs.name = {x: ""
                       for x in range(1, playercount + 1)
                       }  # only so it can be overwrittin in mystery
        erargs.create_spoiler = not race
        erargs.race = race
        erargs.skip_playthrough = race
        erargs.outputname = seedname
        erargs.outputpath = target.name
        erargs.teams = 1
        erargs.progression_balancing = {}
        erargs.create_diff = True

        for player, (playerfile,
                     settings) in enumerate(gen_options.items(), 1):
            for k, v in vars(settings).items():
                if v is not None:
                    getattr(erargs, k)[player] = v

            if not erargs.name[player]:
                erargs.name[player] = os.path.split(playerfile)[-1].split(
                    ".")[0]

        erargs.names = ",".join(erargs.name[i]
                                for i in range(1, playercount + 1))
        del (erargs.name)

        erargs.skip_progression_balancing = {
            player: not balanced
            for player, balanced in erargs.progression_balancing.items()
        }
        del (erargs.progression_balancing)
        ERmain(erargs, seed)
        return upload_to_db(target.name)
示例#4
0
def main(args=None, callback=ERmain):
    if not args:
        args = mystery_argparse()

    seed = get_seed(args.seed)
    random.seed(seed)

    seedname = "M" + (
        f"{random.randint(0, pow(10, seeddigits) - 1)}".zfill(seeddigits))
    print(
        f"Generating mystery for {args.multi} player{'s' if args.multi > 1 else ''}, {seedname} Seed {seed}"
    )

    if args.race:
        random.seed()  # reset to time-based random source

    weights_cache = {}
    if args.weights:
        try:
            weights_cache[args.weights] = get_weights(args.weights)
        except Exception as e:
            raise ValueError(
                f"File {args.weights} is destroyed. Please fix your yaml."
            ) from e
        print(
            f"Weights: {args.weights} >> "
            f"{get_choice('description', weights_cache[args.weights], 'No description specified')}"
        )
    if args.meta:
        try:
            weights_cache[args.meta] = get_weights(args.meta)
        except Exception as e:
            raise ValueError(
                f"File {args.meta} is destroyed. Please fix your yaml.") from e
        meta_weights = weights_cache[args.meta]
        print(
            f"Meta: {args.meta} >> {get_choice('meta_description', meta_weights, 'No description specified')}"
        )
        if args.samesettings:
            raise Exception("Cannot mix --samesettings with --meta")

    for player in range(1, args.multi + 1):
        path = getattr(args, f'p{player}')
        if path:
            try:
                if path not in weights_cache:
                    weights_cache[path] = get_weights(path)
                print(
                    f"P{player} Weights: {path} >> "
                    f"{get_choice('description', weights_cache[path], 'No description specified')}"
                )

            except Exception as e:
                raise ValueError(
                    f"File {path} is destroyed. Please fix your yaml.") from e
    erargs = parse_arguments(['--multi', str(args.multi)])
    erargs.seed = seed
    erargs.name = {x: ""
                   for x in range(1, args.multi + 1)
                   }  # only so it can be overwrittin in mystery
    erargs.create_spoiler = args.create_spoiler
    erargs.create_diff = args.create_diff
    erargs.glitch_triforce = args.glitch_triforce
    erargs.race = args.race
    erargs.skip_playthrough = args.skip_playthrough
    erargs.outputname = seedname
    erargs.outputpath = args.outputpath
    erargs.teams = args.teams
    erargs.progression_balancing = {}

    # set up logger
    if args.loglevel:
        erargs.loglevel = args.loglevel
    loglevel = {
        'error': logging.ERROR,
        'info': logging.INFO,
        'warning': logging.WARNING,
        'debug': logging.DEBUG
    }[erargs.loglevel]

    if args.log_output_path:
        import sys

        class LoggerWriter(object):
            def __init__(self, writer):
                self._writer = writer
                self._msg = ''

            def write(self, message):
                self._msg = self._msg + message
                while '\n' in self._msg:
                    pos = self._msg.find('\n')
                    self._writer(self._msg[:pos])
                    self._msg = self._msg[pos + 1:]

            def flush(self):
                if self._msg != '':
                    self._writer(self._msg)
                    self._msg = ''

        log = logging.getLogger("stderr")
        log.addHandler(logging.StreamHandler())
        sys.stderr = LoggerWriter(log.error)
        os.makedirs(args.log_output_path, exist_ok=True)
        logging.basicConfig(format='%(message)s',
                            level=loglevel,
                            filename=os.path.join(args.log_output_path,
                                                  f"{seed}.log"))
    else:
        logging.basicConfig(format='%(message)s', level=loglevel)
    if args.rom:
        erargs.rom = args.rom

    if args.enemizercli:
        erargs.enemizercli = args.enemizercli

    settings_cache = {
        k: (roll_settings(v, args.plando) if args.samesettings else None)
        for k, v in weights_cache.items()
    }
    player_path_cache = {}
    for player in range(1, args.multi + 1):
        player_path_cache[player] = getattr(args, f'p{player}') if getattr(
            args, f'p{player}') else args.weights

    if args.meta:
        for player, path in player_path_cache.items():
            weights_cache[path].setdefault("meta_ignore", [])
        meta_weights = weights_cache[args.meta]
        for key in meta_weights:
            option = get_choice(key, meta_weights)
            if option is not None:
                for player, path in player_path_cache.items():
                    players_meta = weights_cache[path].get("meta_ignore", [])
                    if key not in players_meta:
                        weights_cache[path][key] = option
                    elif type(players_meta) == dict and players_meta[
                            key] and option not in players_meta[key]:
                        weights_cache[path][key] = option

    name_counter = Counter()
    for player in range(1, args.multi + 1):
        path = player_path_cache[player]
        if path:
            try:
                settings = settings_cache[path] if settings_cache[path] else \
                    roll_settings(weights_cache[path], args.plando)
                if settings.sprite and not os.path.isfile(
                        settings.sprite) and not Sprite.get_sprite_from_name(
                            settings.sprite):
                    logging.warning(
                        f"Warning: The chosen sprite, \"{settings.sprite}\", for yaml \"{path}\", does not exist."
                    )
                if args.pre_roll:
                    import yaml
                    if path == args.weights:
                        settings.name = f"Player{player}"
                    elif not settings.name:
                        settings.name = os.path.splitext(
                            os.path.split(path)[-1])[0]

                    if "-" not in settings.shuffle and settings.shuffle != "vanilla":
                        settings.shuffle += f"-{random.randint(0, 2 ** 64)}"

                    pre_rolled = dict()
                    pre_rolled["original_seed_number"] = seed
                    pre_rolled["original_seed_name"] = seedname
                    pre_rolled["pre_rolled"] = vars(settings).copy()
                    if "plando_items" in pre_rolled["pre_rolled"]:
                        pre_rolled["pre_rolled"]["plando_items"] = [
                            item.to_dict() for item in pre_rolled["pre_rolled"]
                            ["plando_items"]
                        ]
                    if "plando_connections" in pre_rolled["pre_rolled"]:
                        pre_rolled["pre_rolled"]["plando_connections"] = [
                            connection.to_dict() for connection in
                            pre_rolled["pre_rolled"]["plando_connections"]
                        ]

                    with open(
                            os.path.join(
                                args.outputpath if args.outputpath else ".",
                                f"{os.path.split(path)[-1].split('.')[0]}_pre_rolled.yaml"
                            ), "wt") as f:
                        yaml.dump(pre_rolled, f)
                for k, v in vars(settings).items():
                    if v is not None:
                        getattr(erargs, k)[player] = v
            except Exception as e:
                raise ValueError(
                    f"File {path} is destroyed. Please fix your yaml.") from e
        else:
            raise RuntimeError(f'No weights specified for player {player}')
        if path == args.weights:  # if name came from the weights file, just use base player name
            erargs.name[player] = f"Player{player}"
        elif not erargs.name[
                player]:  # if name was not specified, generate it from filename
            erargs.name[player] = os.path.splitext(os.path.split(path)[-1])[0]
        erargs.name[player] = handle_name(erargs.name[player], player,
                                          name_counter)
        logging.info(erargs.name[player])
    erargs.names = ",".join(erargs.name[i] for i in range(1, args.multi + 1))
    del (erargs.name)
    if args.yaml_output:
        import yaml
        important = {}
        for option, player_settings in vars(erargs).items():
            if type(player_settings) == dict:
                if all(
                        type(value) != list
                        for value in player_settings.values()):
                    if len(player_settings.values()) > 1:
                        important[option] = {
                            player: value
                            for player, value in player_settings.items()
                            if player <= args.yaml_output
                        }
                    elif len(player_settings.values()) > 0:
                        important[option] = player_settings[1]
                    else:
                        logging.debug(
                            f"No player settings defined for option '{option}'"
                        )

            else:
                if player_settings != "":  # is not empty name
                    important[option] = player_settings
                else:
                    logging.debug(
                        f"No player settings defined for option '{option}'")
        if args.outputpath:
            os.makedirs(args.outputpath, exist_ok=True)
        with open(
                os.path.join(args.outputpath if args.outputpath else ".",
                             f"mystery_result_{seed}.yaml"), "wt") as f:
            yaml.dump(important, f)

    erargs.skip_progression_balancing = {
        player: not balanced
        for player, balanced in erargs.progression_balancing.items()
    }
    del (erargs.progression_balancing)
    callback(erargs, seed)